package com.iplant.aps.serviceimpl;

import com.alibaba.fastjson.JSON;
import com.iplant.aps.service.SFCService;
import com.iplant.aps.service.mesenum.*;
import com.iplant.aps.service.po.APIResult;
import com.iplant.aps.service.po.OutResult;
import com.iplant.aps.service.po.ServiceResult;
import com.iplant.aps.service.po.aps.APSBOMItem;
import com.iplant.aps.service.po.aps.APSTaskPart;
import com.iplant.aps.service.po.aps.APSTaskStep;
import com.iplant.aps.service.po.bfc.BFCMessage;
import com.iplant.aps.service.po.bms.BMSClassPartRole;
import com.iplant.aps.service.po.bms.BMSEmployee;
import com.iplant.aps.service.po.bms.BMSRoleItem;
import com.iplant.aps.service.po.bms.BMSWorkCharge;
import com.iplant.aps.service.po.bpm.BPMActivitiHisTask;
import com.iplant.aps.service.po.bpm.BPMActivitiHisTaskVarinst;
import com.iplant.aps.service.po.bpm.BPMActivitiTask;
import com.iplant.aps.service.po.bpm.BPMTaskBase;
import com.iplant.aps.service.po.cfg.CFGItem;
import com.iplant.aps.service.po.excel.ExcelData;
import com.iplant.aps.service.po.excel.ExcelLineData;
import com.iplant.aps.service.po.excel.ExcelSheetData;
import com.iplant.aps.service.po.excel.MyExcelSheet;
import com.iplant.aps.service.po.fmc.FMCWorkCharge;
import com.iplant.aps.service.po.fpc.FPCPart;
import com.iplant.aps.service.po.fpc.FPCPartPoint;
import com.iplant.aps.service.po.fpc.FPCRoutePart;
import com.iplant.aps.service.po.fpc.FPCRoutePartPoint;
import com.iplant.aps.service.po.ipt.IPTOutsourcingMaterial;
import com.iplant.aps.service.po.ipt.IPTPreCheckProblem;
import com.iplant.aps.service.po.ipt.IPTValue;
import com.iplant.aps.service.po.lfs.LFSOperationLog;
import com.iplant.aps.service.po.lfs.LFSWorkAreaChecker;
import com.iplant.aps.service.po.lfs.LFSWorkAreaStation;
import com.iplant.aps.service.po.mbs.MBSApiLogAnalysis;
import com.iplant.aps.service.po.mbs.MBSApiLogDetails;
import com.iplant.aps.service.po.mss.MSSBOM;
import com.iplant.aps.service.po.mss.MSSBOMItem;
import com.iplant.aps.service.po.mss.MSSBOMItemHistory;
import com.iplant.aps.service.po.mss.MSSMaterial;
import com.iplant.aps.service.po.oms.OMSOrder;
import com.iplant.aps.service.po.rro.RROItemTask;
import com.iplant.aps.service.po.sch.SCHSecondmentApply;
import com.iplant.aps.service.po.sfc.*;
import com.iplant.aps.service.po.tcm.TCMMaterialChangeLog;
import com.iplant.aps.service.po.wms.WMSBatchPickDemand;
import com.iplant.aps.service.po.wms.WMSBatchPickDemandItem;
import com.iplant.aps.service.po.wms.WMSLineEdgeLibrary;
import com.iplant.aps.service.utils.CloneTool;
import com.iplant.aps.service.utils.DesUtil;
import com.iplant.aps.service.utils.StringUtils;
import com.iplant.aps.serviceimpl.dao.BaseDAO;
import com.iplant.aps.serviceimpl.dao.andon.AndonDAO;
import com.iplant.aps.serviceimpl.dao.aps.APSBOMItemDAO;
import com.iplant.aps.serviceimpl.dao.aps.APSTaskPartDAO;
import com.iplant.aps.serviceimpl.dao.aps.APSTaskStepDAO;
import com.iplant.aps.serviceimpl.dao.bms.BMSClassPartRoleDAO;
import com.iplant.aps.serviceimpl.dao.mes.MESSystemConfigDAO;
import com.iplant.aps.serviceimpl.dao.mss.MSSBOMItemDAO;
import com.iplant.aps.serviceimpl.dao.mss.MSSBOMItemHistoryDAO;
import com.iplant.aps.serviceimpl.dao.oms.OMSOrderDAO;
import com.iplant.aps.serviceimpl.dao.sch.SCHSecondmentApplyDAO;
import com.iplant.aps.serviceimpl.dao.sfc.*;
import com.iplant.aps.serviceimpl.dao.tcm.TCMMaterialChangeLogDAO;
import com.iplant.aps.serviceimpl.dao.wms.WMSBatchPickDemandDAO;
import com.iplant.aps.serviceimpl.dao.wms.WMSBatchPickDemandItemDAO;
import com.iplant.aps.serviceimpl.dao.wms.WMSLineEdgeLibraryDAO;
import com.iplant.aps.serviceimpl.utils.MESServer;
import com.iplant.aps.serviceimpl.utils.aps.APSConstans;
import com.iplant.aps.serviceimpl.utils.aps.APSUtils;
import com.iplant.aps.serviceimpl.utils.sap.ZIF_MM_GET_WMS281_WSStub;
import com.iplant.aps.utils.RetCode;
import com.iplant.aps.utils.aps.ExcelUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

@Service
public class SFCServiceImpl implements SFCService {
    private static final Logger logger = LoggerFactory.getLogger(SFCServiceImpl.class);

    private static SFCService Instance;

    public static SFCService getInstance() {
        if (Instance == null)
            Instance = new SFCServiceImpl();
        return Instance;
    }

    public ServiceResult<SFCTaskStep> SFC_QueryTaskStep(BMSEmployee wLoginUser, int wID) {
        ServiceResult<SFCTaskStep> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            wResult.Result = SFCTaskStepDAO.getInstance().SelectByID(wLoginUser, wID, wErrorCode);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            logger.error(e.toString());
        }
        return wResult;
    }

    public ServiceResult<List<SFCTaskStep>> SFC_QueryTaskStepList(BMSEmployee wLoginUser, int wID, int wTaskStepID,
                                                                  int wShiftID, int wOpeartorID, int wMonitorID) {
        ServiceResult<List<SFCTaskStep>> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            if (wID <= 0 && wTaskStepID <= 0 && wShiftID <= 0) {
                wResult.Result = new ArrayList<>();
                return wResult;
            }

            wResult.Result = SFCTaskStepDAO.getInstance().SelectList(wLoginUser, wID, wTaskStepID, wShiftID,
                    wOpeartorID, wMonitorID, null, -1, wErrorCode);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            logger.error(e.toString());
        }
        return wResult;
    }

    public ServiceResult<Integer> SFC_UpdateTaskStep(BMSEmployee wLoginUser, SFCTaskStep wSFCTaskStep) {
        ServiceResult<Integer> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            wResult.Result = SFCTaskStepDAO.getInstance().Update(wLoginUser, wSFCTaskStep, wErrorCode);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            logger.error(e.toString());
        }
        return wResult;
    }

    public ServiceResult<List<BMSEmployee>> SFC_QueryDispatchEmployeeList(BMSEmployee wLoginUser, boolean wIsRemove,
                                                                          List<Integer> wAPSTaskStepIDList) {
        ServiceResult<List<BMSEmployee>> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            wResult.Result = new ArrayList<>();

            List<BMSEmployee> wEmployeeList = CoreServiceImpl.getInstance().BMS_GetEmployeeAll(wLoginUser, 0, 0, 1)
                    .List(BMSEmployee.class);
            if (wEmployeeList == null || wEmployeeList.size() <= 0) {
                return wResult;
            }
            if ((APSConstans.GetBMSDepartment(wLoginUser.DepartmentID)).Type != BMSDepartmentType.Class.getValue()
                    || (APSConstans.GetBMSPosition(wLoginUser.Position)).DutyID != 1) {
                return wResult;
            }

            wResult.Result = wEmployeeList.stream().filter(p -> (p.DepartmentID == wLoginUser.DepartmentID))
                    .collect(Collectors.toList());

            List<SCHSecondmentApply> wSecondList = SCHSecondmentApplyDAO.getInstance().SelectListByClass(wLoginUser, -1,
                    wLoginUser.DepartmentID, new ArrayList<>(Collections.singletonList(20)), wErrorCode);
            wSecondList = wSecondList.stream().filter(p -> Calendar.getInstance().compareTo(p.StartTime) >= 0
                    && Calendar.getInstance().compareTo(p.EndTime) <= 0).collect(Collectors.toList());

            if (wSecondList.size() > 0) {
                for (SCHSecondmentApply wItem : wSecondList) {

                    String[] wIDs = wItem.PersonID.split(",");
                    for (String wID : wIDs) {
                        int wUserID = StringUtils.parseInt(wID);
                        if (wUserID > 0) {
                            if (wEmployeeList.stream().anyMatch(p -> p.ID == wUserID)) {
                                BMSEmployee wPersonItem = wEmployeeList.stream().filter(p -> (p.ID == wUserID))
                                        .findFirst().get();
                                wPersonItem.Name = StringUtils.Format("{0}({1})", wPersonItem.Name,
                                        APSConstans.GetBMSDepartmentName(wPersonItem.DepartmentID));
                                wResult.Result.add(wPersonItem);
                            }
                        }
                    }
                }
            }

            if (wIsRemove) {
                for (Integer wAPSTaskStepID : wAPSTaskStepIDList) {
                    ServiceResult<List<SFCTaskStep>> wTaskList = this.SFC_QueryTaskStepList(wLoginUser, -1,
                            wAPSTaskStepID, -1, -1, -1);
                    // 去除已经派工的人员列表
                    if (wResult.Result != null && wResult.Result.size() > 0 && wTaskList != null
                            && wTaskList.Result != null && wTaskList.Result.size() > 0) {
                        wResult.Result.removeIf(p -> wTaskList.Result.stream().anyMatch(q -> q.OperatorID == p.ID));
                    }
                }
            }

            // 赋值工号
            if (wResult.Result != null && wResult.Result.size() > 0) {
                for (BMSEmployee wUser : wResult.Result) {
                    if (StringUtils.isEmpty(wUser.LoginID) || wUser.LoginID.length() != 12) {
                        continue;
                    }
                    wUser.Name = StringUtils.Format("{0}({1})", wUser.Name, wUser.LoginID.substring(7));
                }
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            logger.error(e.toString());
        }
        return wResult;
    }

    public ServiceResult<List<SFCTaskStep>> SFC_QueryTaskStepListByEmployeeID(BMSEmployee wLoginUser,
                                                                              Calendar wStartTime, Calendar wEndTime,
                                                                              int wTagTypes) {
        ServiceResult<List<SFCTaskStep>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            wResult.Result = SFCTaskStepDAO.getInstance().SelectListByTime(wLoginUser, wLoginUser.ID, wStartTime,
                    wEndTime, wErrorCode);

            if (wResult.Result.size() <= 0) {
                return wResult;
            }

            List<SFCTaskStep> wAllSFCTaskStepList = new ArrayList<>();

            List<Integer> wStepTaskStepIDList = (wResult.Result).stream()
                    .filter(p -> (p.Type == SFCTaskStepType.Step.getValue())).map(p -> p.TaskStepID)
                    .collect(Collectors.toList());
            if (wStepTaskStepIDList.size() > 0) {
                List<SFCTaskStep> wTempList = SFCTaskStepDAO.getInstance().SelectListByTaskStepIDList(wLoginUser,
                        wStepTaskStepIDList, SFCTaskStepType.Step.getValue(), wErrorCode);
                if (wTempList != null && wTempList.size() > 0) {
                    wAllSFCTaskStepList.addAll(wTempList);
                }
            }

            List<Integer> wQuestionTaskStepIDList = (wResult.Result).stream()
                    .filter(p -> (p.Type == SFCTaskStepType.Question.getValue()))
                    .map(p -> p.TaskStepID).collect(Collectors.toList());
            if (wQuestionTaskStepIDList.size() > 0) {
                List<SFCTaskStep> wTempList = SFCTaskStepDAO.getInstance().SelectListByTaskStepIDList(wLoginUser,
                        wQuestionTaskStepIDList, SFCTaskStepType.Question.getValue(), wErrorCode);
                if (wTempList != null && wTempList.size() > 0) {
                    wAllSFCTaskStepList.addAll(wTempList);
                }
            }

            List<Integer> wQualityTaskStepIDList = (wResult.Result).stream()
                    .filter(p -> (p.Type == SFCTaskStepType.Quality.getValue())).map(p -> p.TaskStepID)
                    .collect(Collectors.toList());
            if (wQualityTaskStepIDList.size() > 0) {
                List<SFCTaskStep> wTempList = SFCTaskStepDAO.getInstance().SelectListByTaskStepIDList(wLoginUser,
                        wQualityTaskStepIDList, SFCTaskStepType.Quality.getValue(), wErrorCode);
                if (wTempList != null && wTempList.size() > 0) {
                    wAllSFCTaskStepList.addAll(wTempList);
                }
            }

            for (SFCTaskStep wSFCTaskStep : wResult.Result) {
                List<SFCTaskStep> wTempList = wAllSFCTaskStepList.stream()
                        .filter(p -> (p.TaskStepID == wSFCTaskStep.TaskStepID && p.Type == wSFCTaskStep.Type))
                        .collect(Collectors.toList());

                if (wTempList.size() <= 0) {
                    continue;
                }
                List<String> wOpeList = wTempList.stream()
                        .map(p -> APSConstans.GetBMSEmployeeName(p.OperatorID)).collect(Collectors.toList());
                wSFCTaskStep.Operators = StringUtils.Join(",", wOpeList);
            }

            // 打卡数据排序
            if (wResult.Result.size() > 0) {
                // ①获取工区 工位列表
                List<LFSWorkAreaStation> wLFSWorkAreaStationList = new ArrayList<>(
                        APSConstans.GetLFSWorkAreaStationList().values());
                // ②工位顺序赋值
                for (SFCTaskStep wSFCTaskStep : wResult.Result) {
                    if (wLFSWorkAreaStationList.stream().anyMatch(p -> p.StationID == wSFCTaskStep.PartID)) {
                        wSFCTaskStep.PartOrderID = wLFSWorkAreaStationList.stream()
                                .filter(p -> p.StationID == wSFCTaskStep.PartID).findFirst().get().OrderNum;
                    }
                }
                // ③分三个状态集合，存不同的数据(未开工、已开工、已完工、已暂停)
                List<SFCTaskStep> wList1;
                wList1 = wResult.Result.stream().filter(p -> p.IsStartWork == SFCLoginType.Default.getValue())
                        .collect(Collectors.toList());
                List<SFCTaskStep> wList2;
                wList2 = wResult.Result.stream().filter(p -> p.IsStartWork == SFCLoginType.StartWork.getValue())
                        .collect(Collectors.toList());
                List<SFCTaskStep> wList3;
                wList3 = wResult.Result.stream().filter(p -> p.IsStartWork == SFCLoginType.AfterWork.getValue())
                        .collect(Collectors.toList());
                List<SFCTaskStep> wList4;
                wList4 = wResult.Result.stream().filter(p -> p.IsStartWork == SFCLoginType.StopWork.getValue())
                        .collect(Collectors.toList());
                // ④未开工排序：车号、工位
                wList1.sort(Comparator.comparing(SFCTaskStep::getPartOrderID).thenComparing(SFCTaskStep::getPartNo));
                // ④暂停排序：车号、工位
                wList4.sort(Comparator.comparing(SFCTaskStep::getPartOrderID).thenComparing(SFCTaskStep::getPartNo));
                // ⑤已开工排序：车号、工位
                wList2.sort(Comparator.comparing(SFCTaskStep::getPartOrderID).thenComparing(SFCTaskStep::getPartNo));
                // ⑥已完工排序：车号、工位
                wList3.sort(Comparator.comparing(SFCTaskStep::getPartOrderID).thenComparing(SFCTaskStep::getPartNo));
                // ⑦添加结果集
                wResult.Result = new ArrayList<>();
                wResult.Result.addAll(wList1);
                wResult.Result.addAll(wList4);
                wResult.Result.addAll(wList2);
                wResult.Result.addAll(wList3);
            }

            // 给问题项类型的数据源赋值项点
            if (wResult.Result.size() > 0) {
                switch (SFCLoginType.getEnumType(wTagTypes)) {
                    case StartWork:
                        wResult.Result = wResult.Result.stream()
                                .filter(p -> p.IsStartWork == SFCLoginType.Default.getValue()
                                        || p.IsStartWork == SFCLoginType.StartWork.getValue()
                                        || p.IsStartWork == SFCLoginType.StopWork.getValue())
                                .collect(Collectors.toList());
                        break;
                    case AfterWork:
                        wResult.Result = wResult.Result.stream()
                                .filter(p -> p.IsStartWork == SFCLoginType.AfterWork.getValue()
                                        || p.IsStartWork == SFCLoginType.StartWork.getValue())
                                .collect(Collectors.toList());
                        break;
                    default:
                        break;
                }

                List<Integer> wProblemIDList = wResult.Result.stream()
                        .filter(p -> p.Type == SFCTaskStepType.Question.getValue()).map(p -> p.TaskStepID)
                        .collect(Collectors.toList());
                if (wProblemIDList.size() <= 0) {
                    return wResult;
                }

                for (SFCTaskStep wSFCTaskStep : wResult.Result) {
                    if (wSFCTaskStep.Type != SFCTaskStepType.Question.getValue()) {
                        continue;
                    }

                    IPTPreCheckProblem wProblem = QMSServiceImpl.getInstance()
                            .IPT_QueryPreCheckProblemByID(wLoginUser, wSFCTaskStep.TaskStepID)
                            .Info(IPTPreCheckProblem.class);
                    if (wProblem == null || wProblem.ID <= 0) {
                        continue;
                    }

                    wSFCTaskStep.PartPointName = wProblem.IPTItemName;
                }
            }
        } catch (Exception e) {
            logger.error(e.toString());
        }
        return wResult;
    }

    public ServiceResult<List<SFCTaskStep>> SFC_QueryTaskStepListByMonitorID(BMSEmployee wLoginUser,
                                                                             Calendar wShiftDate) {
        ServiceResult<List<SFCTaskStep>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);

        try {
            int wShiftID = MESServer.MES_QueryShiftID(wLoginUser.CompanyID, Calendar.getInstance(), APSShiftPeriod.Day,
                    FMCShiftLevel.Day, 0);

            wResult.Result = SFCTaskStepDAO.getInstance().SelectList(wLoginUser, -1, -1, wShiftID, -1, wLoginUser.ID,
                    null, -1, wErrorCode);

        } catch (Exception e) {
            logger.error(e.toString());
        }
        return wResult;
    }

    public ServiceResult<Integer> SFC_AdjustHour(BMSEmployee wLoginUser, List<SFCTaskStep> wSFCTaskStepList,
                                                 Double wHour) {
        ServiceResult<Integer> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            for (SFCTaskStep wSFCTaskStep : wSFCTaskStepList) {
                wSFCTaskStep.WorkHour = wHour;
                SFCTaskStepDAO.getInstance().Update(wLoginUser, wSFCTaskStep, wErrorCode);
            }
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode = wResult.FaultCode + e;
            logger.error(e.toString());
        }
        return wResult;
    }

    public ServiceResult<Map<Integer, List<Integer>>> SFC_QueryStepPersonMap(BMSEmployee wLoginUser,
                                                                             List<APSTaskStep> wAPSTaskStepList) {
        ServiceResult<Map<Integer, List<Integer>>> wResult = new ServiceResult<>();
        wResult.Result = new HashMap<>();
        try {
            if (wAPSTaskStepList == null || wAPSTaskStepList.size() <= 0) {
                return wResult;
            }

            OutResult<Integer> wErrorCode = new OutResult<>(0);

            // 获取所有有效的员工列表(Active=1)
            List<BMSEmployee> wActiveEmployeeList = APSConstans.GetBMSEmployeeList().values().stream()
                    .filter(p -> p.Active == 1)
                    .collect(Collectors.toList());

            // 获取有效员工ID列表
            List<Integer> wActiveEmployeeIDList = wActiveEmployeeList.stream()
                    .map(p -> p.ID)
                    .collect(Collectors.toList());

            List<SFCDefaultPerson> wList;
            for (APSTaskStep wAPSTaskStep : wAPSTaskStepList) {
                wList = SFCDefaultPersonDAO.getInstance().SelectList(wLoginUser, -1,
                        APSConstans.GetFPCProducID(wAPSTaskStep.ProductNo), wAPSTaskStep.LineID, wAPSTaskStep.PartID,
                        wAPSTaskStep.StepID, wErrorCode);

                if (wList != null && wList.size() > 0) {
                    // 过滤掉已禁用的人员ID
                    List<Integer> wFilteredPersonList = wList.get(0).PersonIDList.stream()
                            .filter(wActiveEmployeeIDList::contains)
                            .collect(Collectors.toList());

                    if (wFilteredPersonList.size() > 0) {
                        wResult.Result.put(wAPSTaskStep.ID, wFilteredPersonList);
                    }
                }
            }
        } catch (Exception e) {
            wResult.FaultCode = wResult.FaultCode + e;
            logger.error(e.toString());
        }
        return wResult;
    }

    public ServiceResult<List<BMSEmployee>> SFC_QueryPGEmployeeList(BMSEmployee wLoginUser, int wID) {
        ServiceResult<List<BMSEmployee>> wResult = new ServiceResult<>();
        try {
            wResult.Result = new ArrayList<>();
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            List<SFCTaskStep> wList = SFCTaskStepDAO.getInstance().SelectList(wLoginUser, -1, wID, -1, -1, -1, null,
                    SFCTaskStepType.Step.getValue(), wErrorCode);
            for (SFCTaskStep wSFCTaskStep : wList) {
                wResult.Result.add(APSConstans.GetBMSEmployee(wSFCTaskStep.OperatorID));
            }
        } catch (Exception e) {
            wResult.FaultCode = wResult.FaultCode + e;
            logger.error(e.toString());
        }
        return wResult;
    }

    /**
     * 关闭消息
     */
    private void CloseMessageList(BMSEmployee wLoginUser, List<SFCTaskStep> wAllSFCTaskStepList) {
        try {
            if (wAllSFCTaskStepList == null || wAllSFCTaskStepList.size() <= 0) {
                return;
            }

            List<BFCMessage> wList = CoreServiceImpl.getInstance().BFC_GetMessageList(wLoginUser, -1,
                            BPMEventModule.SCDispatching.getValue(), BFCMessageType.Task.getValue(), -1, -1, null, null)
                    .List(BFCMessage.class);
            if (wList == null || wList.size() <= 0) {
                return;
            }

            wList = wList.stream().filter(p -> wAllSFCTaskStepList.stream().anyMatch(q -> q.ID == p.MessageID)
                    && (p.Active == 0 || p.Active == 1 || p.Active == 2)).collect(Collectors.toList());

            if (wList.size() <= 0) {
                return;
            }

            wList.forEach(p -> p.Active = BFCMessageStatus.Close.getValue());

            CoreServiceImpl.getInstance().BFC_UpdateMessageList(wLoginUser, wList);
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    /**
     * 更新默认人员
     */
    private void UpdateDefaultPerson(BMSEmployee wLoginUser, OutResult<Integer> wErrorCode, int wNewID,
                                     APSTaskStep wAPSTaskStep) {
        try {
            // 去重默认人员ID
            if (wAPSTaskStep.OperatorList != null && wAPSTaskStep.OperatorList.size() > 0) {
                wAPSTaskStep.OperatorList = wAPSTaskStep.OperatorList.stream().distinct().collect(Collectors.toList());
            }

            SFCTaskStep wNewItem = SFCTaskStepDAO.getInstance().SelectByID(wLoginUser, wNewID, wErrorCode);
            List<SFCDefaultPerson> wDefaultList = SFCDefaultPersonDAO.getInstance().SelectList(wLoginUser, -1,
                    wNewItem.ProductID, wNewItem.LineID, wNewItem.PartID, wNewItem.StepID, wErrorCode);
            if (wDefaultList != null && wDefaultList.size() > 0) {
                wDefaultList.get(0).PersonIDList = wAPSTaskStep.OperatorList;
                SFCDefaultPersonDAO.getInstance().Update(wLoginUser, wDefaultList.get(0), wErrorCode);
            } else {
                SFCDefaultPerson wSFCDefaultPerson = new SFCDefaultPerson();
                wSFCDefaultPerson.ID = 0;
                wSFCDefaultPerson.LineID = wNewItem.LineID;
                wSFCDefaultPerson.PartID = wNewItem.PartID;
                wSFCDefaultPerson.PartPointID = wNewItem.StepID;
                wSFCDefaultPerson.PersonIDList = wAPSTaskStep.OperatorList;
                wSFCDefaultPerson.ProductID = APSConstans.GetFPCProducID(wNewItem.ProductNo);
                SFCDefaultPersonDAO.getInstance().Update(wLoginUser, wSFCDefaultPerson, wErrorCode);
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    private void CreateMessage(BMSEmployee wLoginUser, int wShiftID, SFCTaskStep wSFCTaskStep, int wNewID,
                               List<BFCMessage> wMessageList, APSTaskStep wAPSTaskStep, int wOperatorID) {
        try {
            BFCMessage wMessage = new BFCMessage();
            wMessage.Active = 0;
            wMessage.CompanyID = 0;
            wMessage.CreateTime = Calendar.getInstance();
            wMessage.EditTime = Calendar.getInstance();
            wMessage.ID = 0L;
            wMessage.MessageID = wNewID;
            wMessage.Title = StringUtils.Format("派工 {0}", wAPSTaskStep.PartNo);
            wMessage.MessageText = StringUtils.Format("【{0}】 {1}派工了[{2}-{3}]，请及时开工打卡!",
                    BPMEventModule.SCDispatching.getLable(),
                    wLoginUser.Name, wAPSTaskStep.PartName, wAPSTaskStep.StepName);
            wMessage.ModuleID = (BPMEventModule.SCDispatching.getValue());
            wMessage.ResponsorID = wOperatorID;
            wMessage.ShiftID = wShiftID;
            wMessage.StationID = wSFCTaskStep.PartID;
            wMessage.Type = BFCMessageType.Task.getValue();
            wMessageList.add(wMessage);
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    public ServiceResult<Integer> SFC_TaskStepSaveAll(BMSEmployee wLoginUser, List<APSTaskStep> wAPSTaskStepList) {
        ServiceResult<Integer> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            List<SFCTaskStep> wAllSFCTaskStepList = SFCTaskStepDAO.getInstance().SelectListByTaskStepIDList(wLoginUser,
                    wAPSTaskStepList.stream().map(p -> p.ID).collect(Collectors.toList()), -1,
                    wErrorCode);

            wAPSTaskStepList.forEach(p -> {
                p.IsDispatched = false;
                APSTaskStepDAO.getInstance().Update(wLoginUser, p, wErrorCode);
            });

            SFCTaskStepDAO.getInstance().DeleteList(wLoginUser, wAllSFCTaskStepList, wErrorCode);

            // 关闭这些派工任务对应的消息
            ExecutorService wES = Executors.newFixedThreadPool(1);
            wES.submit(() -> CloseMessageList(wLoginUser, wAllSFCTaskStepList));
            wES.shutdown();

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode = wResult.FaultCode + e;
            logger.error(e.toString());
        }
        return wResult;
    }

    public ServiceResult<Integer> SFC_SubmitPGProblems(BMSEmployee wLoginUser, List<IPTPreCheckProblem> wDataList) {
        ServiceResult<Integer> wResult = new ServiceResult<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            List<SFCTaskStep> wTaskStepList;

            if (wDataList.stream().anyMatch(p -> p.DoPersonID <= 0)) {
                wResult.FaultCode += "提示：派工人员不能为空!";
                return wResult;
            }

            Calendar wBaseTime = Calendar.getInstance();
            wBaseTime.set(2000, 0, 1);
            int wShiftID = MESServer.MES_QueryShiftID(wLoginUser.CompanyID, Calendar.getInstance(), APSShiftPeriod.Day,
                    FMCShiftLevel.Day, 0);
            int wNewID = 0;
            List<BFCMessage> wMessageList = new ArrayList<>();

            Map<Integer, OMSOrder> wOrderMap = new HashMap<>();
            if (wDataList.size() > 0) {
                List<Integer> wOrderIDList = wDataList.stream().filter(p -> p.OrderID > 0).map(p -> p.OrderID)
                        .distinct().collect(Collectors.toList());

                if (wOrderIDList.size() > 0) {
                    wOrderMap = OMSOrderDAO.getInstance().SelectListByIDList(wLoginUser, wOrderIDList, wErrorCode)
                            .stream().collect(Collectors.toMap(p -> p.ID, p -> p));
                }

            }

            OMSOrder wOMSOrder;
            for (IPTPreCheckProblem wIPTPreCheckProblem : wDataList) {
                wTaskStepList = SFCTaskStepDAO.getInstance().SelectListByType(wLoginUser,
                        SFCTaskStepType.Question.getValue(), wIPTPreCheckProblem.ID, wErrorCode);
                if (wTaskStepList != null && wTaskStepList.size() > 0) {
                    SFCTaskStepDAO.getInstance().DeleteList(wLoginUser, wTaskStepList, wErrorCode);
                }
                wOMSOrder = wOrderMap.containsKey(wIPTPreCheckProblem.OrderID)
                        ? wOrderMap.get(wIPTPreCheckProblem.OrderID)
                        : new OMSOrder();

                SFCTaskStep wSFCTaskStep = new SFCTaskStep();
                wSFCTaskStep.TaskStepID = wIPTPreCheckProblem.ID;
                wSFCTaskStep.CreateTime = Calendar.getInstance();
                wSFCTaskStep.EndTime = wBaseTime;
                wSFCTaskStep.ShiftID = wShiftID;
                wSFCTaskStep.WorkHour = 0.0D;
                wSFCTaskStep.OperatorID = wIPTPreCheckProblem.DoPersonID;
                wSFCTaskStep.ReadyTime = Calendar.getInstance();
                wSFCTaskStep.MonitorID = wLoginUser.ID;
                wSFCTaskStep.Type = SFCTaskStepType.Question.getValue();
                wNewID = (SFC_UpdateTaskStep(wLoginUser, wSFCTaskStep)).Result;

                BFCMessage wMessage = new BFCMessage();
                wMessage.Active = 0;
                wMessage.CompanyID = 0;
                wMessage.CreateTime = Calendar.getInstance();
                wMessage.EditTime = Calendar.getInstance();
                wMessage.ID = 0L;
                wMessage.MessageID = wNewID;
                wMessage.Title = StringUtils.Format("问题项派工 {0}", wOMSOrder.PartNo);
                wMessage.MessageText = StringUtils.Format("【问题项派工】 {0}派工了[{1}],请及时开工打卡!",
                        wLoginUser.Name, wIPTPreCheckProblem.IPTItemName);
                wMessage.ModuleID = BPMEventModule.SCDispatching.getValue();
                wMessage.ResponsorID = wIPTPreCheckProblem.DoPersonID;
                wMessage.ShiftID = wShiftID;
                wMessage.StationID = 0L;
                wMessage.StepID = 1;
                wMessage.Type = BFCMessageType.Task.getValue();
                wMessageList.add(wMessage);

                wIPTPreCheckProblem.IsDischarged = true;
                QMSServiceImpl.getInstance().IPT_UpdatePreCheckProblem(wLoginUser, wIPTPreCheckProblem);
            }

            CoreServiceImpl.getInstance().BFC_UpdateMessageList(wLoginUser, wMessageList);

            wResult.Result = wNewID;
        } catch (Exception e) {
            wResult.FaultCode = wResult.FaultCode + e;
            logger.error(e.toString());
        }
        return wResult;
    }

    public ServiceResult<SFCOrderForm> SFC_QueryOrderForm(BMSEmployee wLoginUser, int wID) {
        ServiceResult<SFCOrderForm> wResult = new ServiceResult<>();
        wResult.Result = new SFCOrderForm();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            wResult.Result = SFCOrderFormDAO.getInstance().SelectByID(wLoginUser, wID, wErrorCode);
            if (wResult.Result != null && (wResult.Result).ID > 0) {
                OMSOrder wOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, (wResult.Result).OrderID,
                        wErrorCode);
                if (wOrder != null && wOrder.ID > 0) {
                    (wResult.Result).LineName = wOrder.LineName;
                    (wResult.Result).ProductNo = wOrder.ProductNo;
                }
            }
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode = wResult.FaultCode + e;
            logger.error(e.toString());
        }
        return wResult;
    }

    public ServiceResult<List<SFCOrderForm>> SFC_QueryCompleteConfirmList(BMSEmployee wLoginUser) {
        ServiceResult<List<SFCOrderForm>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            wResult.Result = SFCOrderFormDAO.getInstance().SelectList(wLoginUser, -1, -1, "", 1, null, wErrorCode);

            if (wResult.Result != null && (wResult.Result).size() > 0) {
                List<Integer> wRemovedList = new ArrayList<>();
                for (SFCOrderForm wSFCOrderForm : wResult.Result) {
                    OMSOrder wOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wSFCOrderForm.OrderID,
                            wErrorCode);
                    if (wOrder != null && wOrder.ID > 0) {
                        wSFCOrderForm.LineName = wOrder.LineName;
                        wSFCOrderForm.ProductNo = wOrder.ProductNo;
                        wSFCOrderForm.CustomerName = wOrder.BureauSection;
                    }
                    // 添加需要移除出厂的数据
                    if (wOrder != null && wOrder.Status == OMSOrderStatus.CarSended.getValue()) {
                        wRemovedList.add(wOrder.ID);
                    }
                }
                for (Integer wOrderID : wRemovedList) {
                    wResult.Result.removeIf(p -> p.OrderID == wOrderID);
                }
            }
        } catch (Exception e) {
            wResult.FaultCode = wResult.FaultCode + e;
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> SFC_CompleteConfirm(BMSEmployee wLoginUser, int wSFCOrderFormID,
                                                      List<String> wImagePathList, String wRemark) {
        ServiceResult<Integer> wResult = new ServiceResult<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            SFCOrderForm wOrderForm = SFCOrderFormDAO.getInstance().SelectByID(wLoginUser, wSFCOrderFormID, wErrorCode);
            if (wOrderForm == null || wOrderForm.ID <= 0) {
                wResult.FaultCode += RetCode.SERVER_RST_ERROR_OUT;
                return wResult;
            }

            OMSOrder wOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wOrderForm.OrderID, wErrorCode);
            if (wOrder == null || wOrder.ID <= 0) {
                wResult.FaultCode += RetCode.SERVER_RST_ERROR_OUT;
                return wResult;
            }

            if (wOrder.Status != OMSOrderStatus.Repairing.getValue()) {
                wResult.FaultCode += "提示：请选择状态为“维修中”的订单!";
                return wResult;
            }

            List<FPCRoutePart> wFPCRoutePartList = FMCServiceImpl.getInstance()
                    .FPC_QueryRoutePartListByRouteID(wLoginUser, 0).List(FPCRoutePart.class);
            List<FPCRoutePartPoint> wFPCRoutePartPointList = FMCServiceImpl.getInstance()
                    .FPC_QueryRoutePartPointListByRouteID(wLoginUser, 0, 0).List(FPCRoutePartPoint.class);

            List<Integer> wPartIDList = APSUtils.getInstance().APS_GetPartIDListByOrder(wOrder,
                    wFPCRoutePartList);
            if (wPartIDList == null || wPartIDList.size() <= 0) {
                wResult.FaultCode += "提示：该订单暂时未设置工艺路线!";
                return wResult;
            }

            // 终检工位列表
            List<FPCPart> wQTFinals = FMCServiceImpl.getInstance()
                    .FPC_QueryPartList(wLoginUser, -1, -1, -1, FPCPartTypes.QTFinally.getValue()).List(FPCPart.class);

            int wRouteID = APSConstans.GetFPCRoute(wOrder.ProductID, wOrder.LineID, wOrder.CustomerID).ID;

            for (int wPartID : wPartIDList) {
                // ③根据订单、工位获取工位任务
                List<APSTaskPart> wTaskPartList = APSTaskPartDAO.getInstance().SelectList(wLoginUser, -1, wOrder.ID, -1,
                        wOrder.LineID, wPartID, 1, APSShiftPeriod.Week.getValue(), null, -1, null, null, wErrorCode);
                if (wTaskPartList == null || wTaskPartList.size() <= 0) {
                    wResult.FaultCode += StringUtils.Format("提示：【{0}】工位任务未下达!", APSConstans.GetFPCPart(wPartID).Name);
                    return wResult;
                }
                // ④根据订单、工位获取所有工序ID集合
                List<Integer> wPartPointIDList = SFC_GetPartPointIDList(wFPCRoutePartList, wFPCRoutePartPointList,
                        wPartID, wRouteID);
                if (wPartPointIDList == null || wPartPointIDList.size() <= 0) {
                    wResult.FaultCode += StringUtils.Format("提示：【{0}】工位下无工序!", APSConstans.GetFPCPart(wPartID).Name);
                    return wResult;
                }
                // ⑤根据工位任务获取所有工序任务列表
                List<APSTaskStep> wTaskStepList = APSTaskStepDAO.getInstance().SelectList(wLoginUser, -1, -1, -1,
                        wTaskPartList.get(0).ID, -1, -1, -1, -1, -1, 1, null, null, null, null, wErrorCode);
                if (wTaskStepList == null || wTaskStepList.size() <= 0) {
                    wResult.FaultCode += StringUtils.Format("提示：【{0}】工位下无工序任务!", APSConstans.GetFPCPart(wPartID).Name);
                    return wResult;
                }
                // ⑥判断是否所有工序都有工序任务，且所有工序任务状态都为完工，若成立，则取，若不成立，则弃。
                if (!wPartPointIDList.stream().allMatch(p -> wTaskStepList.stream()
                        .anyMatch(q -> p == q.StepID && q.Status == APSTaskStatus.Done.getValue()))) {
                    Integer wStepID = wPartPointIDList.stream()
                            .filter(p -> wTaskStepList.stream()
                                    .noneMatch(q -> p == q.StepID && q.Status == APSTaskStatus.Done.getValue()))
                            .findFirst().get();
                    wResult.FaultCode += StringUtils.Format("提示：【{0}】工位下【{1}】工序未完工!",
                            APSConstans.GetFPCPart(wPartID).Name, APSConstans.GetFPCPartPointName(wStepID));
                    return wResult;
                }
                // ⑦判断此工位是否有质量工位触发，且该工位的工序任务全部完工
                if (wQTFinals != null && wQTFinals.size() > 0
                        && wQTFinals.stream().anyMatch(p -> p.QTPartID == wPartID)) {
                    List<FPCPart> wTempPartList = wQTFinals.stream().filter(p -> p.QTPartID == wPartID)
                            .collect(Collectors.toList());
                    for (FPCPart wItem : wTempPartList) {
                        // 获取该工位下所有工序
                        List<Integer> wQTStepIDList = APSUtils.getInstance().FMC_QueryStepIDList(wLoginUser,
                                wOrder.LineID, wItem.ID, wOrder.ProductID);
                        if (wQTStepIDList == null || wQTStepIDList.size() <= 0) {
                            wResult.FaultCode += StringUtils.Format("提示：【{0}】工位下无工序!",
                                    APSConstans.GetFPCPartName(wItem.ID));
                            return wResult;
                        }
                        for (int wStepID : wQTStepIDList) {
                            List<APSTaskStep> wQTStepTaskList = APSTaskStepDAO.getInstance().SelectList(wLoginUser, -1,
                                    wOrder.ID, -1, -1, -1, wOrder.LineID, wItem.ID, wStepID, -1, 1, null, null, null,
                                    null, wErrorCode);
                            if (wQTStepTaskList == null || wQTStepIDList.size() <= 0) {
                                wResult.FaultCode += StringUtils.Format("提示：【{0}】工位下【{1}】工序未生成日计划!",
                                        APSConstans.GetFPCPartName(wItem.ID));
                                return wResult;
                            }
                            if (wQTStepTaskList.stream().anyMatch(p -> p.Status != APSTaskStatus.Done.getValue())) {
                                wResult.FaultCode += StringUtils.Format("提示：【{0}】工位下【{1}】工序未完工!",
                                        APSConstans.GetFPCPartName(wItem.ID));
                                return wResult;
                            }
                            // 判断所有不合格项是否发起不合格评审
                            String wCheckResult = this.IsSendRepair(wLoginUser, wOrder, wItem.ID, wStepID);
                            if (StringUtils.isNotEmpty(wCheckResult)) {
                                wResult.FaultCode += wCheckResult;
                                return wResult;
                            }
                        }
                    }
                }
            }

            // ⑧检查该订单的不合格评审单是否全部完成
            int wNCRNumber = AndonDAO.getInstance().SelectNcrCountNF(wLoginUser, wOrder.ID, null, wErrorCode);
            if (wNCRNumber > 0) {
                wResult.FaultCode += "提示：该订单有未完成的不合格评审单!";
                return wResult;
            }
            // ⑨检查该订单的返修单是否全部完成
            int wRepairNumber = AndonDAO.getInstance().SelectRepairCountNF(wLoginUser, wOrder.ID, null, wErrorCode);
            if (wRepairNumber > 0) {
                wResult.FaultCode += "提示：该订单有未完成的返修单!";
                return wResult;
            }

            // ⑩生成竣工确认单，且将订单状态改为已完工
            wOrderForm.ConfirmID = wLoginUser.ID;
            wOrderForm.ConfirmTime = Calendar.getInstance();
            wOrderForm.Status = 2;
            if (wImagePathList != null && wImagePathList.size() > 0) {
                wOrderForm.ImagePathList = wImagePathList;
            }
            if (StringUtils.isNotEmpty(wRemark)) {
                wOrderForm.Remark = wRemark;
            }
            SFCOrderFormDAO.getInstance().Update(wLoginUser, wOrderForm, wErrorCode);

            wOrder.Status = OMSOrderStatus.FinishedWork.getValue();
            wOrder.RealFinishDate = Calendar.getInstance();
            OMSOrderDAO.getInstance().Update(BaseDAO.SysAdmin, wOrder, wErrorCode);
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    /**
     * 判断某订单的终检工位、工序任务不合格检验项是否发起返修
     */
    private String IsSendRepair(BMSEmployee wLoginUser, OMSOrder wOrder, int wPartID, int wStepID) {
        String wResult = "";
        try {
            List<SFCTaskIPT> wIPTList = QMSServiceImpl.getInstance().SFC_QueryTaskIPTList(wLoginUser, wOrder.ID)
                    .List(SFCTaskIPT.class);
            if (wIPTList == null || wIPTList.size() <= 0) {
                return wResult;
            }
            List<SFCTaskIPT> wTaskIPTList = wIPTList.stream().filter(
                            p -> p.PartID == wPartID && p.PartPointID == wStepID && p.TaskType == SFCTaskType.Final.getValue())
                    .collect(Collectors.toList());
            if (wTaskIPTList.size() <= 0) {
                return wResult;
            }

            for (SFCTaskIPT wSFCTaskIPT : wTaskIPTList) {
                List<IPTValue> wValueList = QMSServiceImpl.getInstance().IPT_QueryValueList(wLoginUser, wSFCTaskIPT.ID)
                        .List(IPTValue.class);
                if (wValueList == null || wValueList.size() <= 0) {
                    continue;
                }
                List<IPTValue> wNotQualityValues = wValueList.stream().filter(p -> p.Result == 2)
                        .collect(Collectors.toList());
                if (wNotQualityValues.size() <= 0) {
                    continue;
                }

                for (IPTValue wIPTValue : wNotQualityValues) {
                    if (!MyHelperServiceImpl.getInstance().WDW_IsSendRepair(wLoginUser, wSFCTaskIPT.ID,
                            (int) wIPTValue.IPTItemID).Result) {
                        wResult = StringUtils.Format("提示：【{0}】工序中有未发起返修的不合格项!", wSFCTaskIPT.PartPointName);
                        return wResult;
                    }
                }
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
        return wResult;
    }

    /**
     * 根据修程、车型、工位获取工序ID集合
     *
     * @param wFPCRoutePartList      工位工艺列表
     * @param wFPCRoutePartPointList 工序工艺列表
     * @param wPartID                工位ID
     * @param wRouteID               修程
     * @return 工序ID集合
     */
    private List<Integer> SFC_GetPartPointIDList(List<FPCRoutePart> wFPCRoutePartList,
                                                 List<FPCRoutePartPoint> wFPCRoutePartPointList, int wPartID,
                                                 int wRouteID) {
        List<Integer> wResult = new ArrayList<>();
        try {
            Optional<FPCRoutePart> wPartOption = wFPCRoutePartList.stream()
                    .filter(p -> p.RouteID == wRouteID && p.PartID == wPartID).findFirst();
            if (!wPartOption.isPresent()) {
                return wResult;
            }

            FPCRoutePart wFPCRoutePart = wPartOption.get();

            List<FPCRoutePartPoint> wList = wFPCRoutePartPointList.stream()
                    .filter(p -> p.PartID == wFPCRoutePart.PartID && p.RouteID == wRouteID)
                    .collect(Collectors.toList());

            if (wList.size() <= 0) {
                return wResult;
            }

            wResult = wList.stream().map(p -> p.PartPointID).collect(Collectors.toList());
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
        return wResult;
    }

    public ServiceResult<SFCOrderForm> SFC_QueryOrderForm(BMSEmployee wLoginUser, int wOrderID, int wType) {
        ServiceResult<SFCOrderForm> wResult = new ServiceResult<>();
        wResult.Result = new SFCOrderForm();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            List<SFCOrderForm> wList = SFCOrderFormDAO.getInstance().SelectList(wLoginUser, -1, wOrderID, "", wType,
                    null, wErrorCode);
            if (wList != null && wList.size() > 0) {
                for (SFCOrderForm wSFCOrderForm : wList) {
                    OMSOrder wOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wSFCOrderForm.OrderID,
                            wErrorCode);
                    if (wOrder == null || wOrder.ID <= 0) {
                        continue;
                    }
                    wSFCOrderForm.LineName = wOrder.LineName;
                    wSFCOrderForm.ProductNo = wOrder.ProductNo;
                    wSFCOrderForm.CustomerName = wOrder.Customer;
                }

                wResult.Result = wList.get(0);
            } else {
                OMSOrder wOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wOrderID, wErrorCode);
                if (wOrder == null || wOrder.ID <= 0) {
                    return wResult;
                }

                wResult.Result = new SFCOrderForm();
                wResult.Result.ID = 0;
                wResult.Result.LineName = wOrder.LineName;
                wResult.Result.ProductNo = wOrder.ProductNo;
                wResult.Result.CustomerName = wOrder.Customer;
                wResult.Result.PartNo = wOrder.PartNo;
                wResult.Result.OrderNo = wOrder.OrderNo;
                wResult.Result.OrderID = wOrderID;
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode = wResult.FaultCode + e;
            logger.error(e.toString());
        }
        return wResult;
    }

    public ServiceResult<List<SFCTaskStep>> SFC_QueryTaskStepList(BMSEmployee wLoginUser,
                                                                  List<Integer> wTaskStepIDList) {
        ServiceResult<List<SFCTaskStep>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            wResult.Result = SFCTaskStepDAO.getInstance().SelectListByTaskStepIDList(wLoginUser, wTaskStepIDList, -1,
                    wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode = wResult.FaultCode + e;
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> SFC_DeleteList(BMSEmployee wLoginUser, List<SFCTaskStep> wList) {
        ServiceResult<Integer> wResult = new ServiceResult<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            wResult = SFCTaskStepDAO.getInstance().DeleteList(wLoginUser, wList, wErrorCode);
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<SFCBOMTask>> SFC_QueryBOMTaskHistory(BMSEmployee wLoginUser, int wID, String wCode,
                                                                   int wUpFlowID, int wFollowerID, int wOrderID,
                                                                   int wPartID, int wPartPointID, int wBOMID,
                                                                   int wLevel,
                                                                   Calendar wStartTime, Calendar wEndTime) {
        ServiceResult<List<SFCBOMTask>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            wResult.Result = SFCBOMTaskDAO.getInstance().SelectList(wLoginUser, wID, wCode, wUpFlowID, "", wOrderID,
                    wPartID, wPartPointID, wBOMID, wLevel, null, wStartTime, wEndTime, wErrorCode);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<BPMTaskBase>> SFC_QueryBOMTaskEmployeeAll(BMSEmployee wLoginUser, int wTagTypes,
                                                                        Calendar wStartTime, Calendar wEndTime) {
        ServiceResult<List<BPMTaskBase>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            switch (TagTypes.getEnumType(wTagTypes)) {
                case Applicant:// 2发起
                    wResult.Result = SFCBOMTaskDAO.getInstance().BPM_GetSendTaskList(wLoginUser, wLoginUser.ID,
                            wStartTime,
                            wEndTime, wErrorCode);
                    break;
                case Dispatcher:// 1待做
                    wResult.Result = SFCBOMTaskDAO.getInstance().BPM_GetUndoTaskList(wLoginUser, wLoginUser.ID,
                            wErrorCode);
                    break;
                case Approver:// 4已做
                    wResult.Result = SFCBOMTaskDAO.getInstance().BPM_GetDoneTaskList(wLoginUser, wLoginUser.ID,
                            wStartTime,
                            wEndTime, wErrorCode);
                    break;
                default:
                    break;
            }

            if (wResult.Result.size() > 0) {
                wResult.Result = wResult.Result.stream().filter(p -> p.Status != 0).collect(Collectors.toList());
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<SFCBOMTask> SFC_SubmitBOMTask(BMSEmployee wLoginUser, SFCBOMTask wTask) {
        ServiceResult<SFCBOMTask> wResult = new ServiceResult<>();
        wResult.Result = new SFCBOMTask();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            if (wTask == null || wTask.ID <= 0) {
                return wResult;
            }

            // 保存物料历史记录
            if (wTask.Status == 2) {
                ExecutorService wES = Executors.newFixedThreadPool(1);
                wES.submit(() -> SaveMaterialHistory(wLoginUser, wTask));
                wES.shutdown();
            }

            if (wTask.Status == SFCBOMTaskStatus.NomalClose.getValue()) {
                wTask.StatusText = SFCBOMTaskStatus.NomalClose.getLable();
            } else if (wTask.Status == SFCBOMTaskStatus.ExceptionClose.getValue()) {
                wTask.StatusText = SFCBOMTaskStatus.ExceptionClose.getLable();
            }

            SimpleDateFormat wSDF = new SimpleDateFormat("yyyyMMdd");
            String wShiftID = wSDF.format(Calendar.getInstance().getTime());

            if (wTask.Status == 66) {
                wTask.StatusText = wTask.StatusText.replace("待(C级)配送班确认,", "");
                wTask.StatusText = wTask.StatusText.replace("待(C级)作业人员确认,", "");
                wTask.ConfirmedLevels += "C";
                wTask.SFCBOMTaskItemList.forEach(p -> {
                    p.NotSend = StringUtils.isNotEmpty(p.ShiftID);
                    if (p.Level == 3 && p.Status != 2) {
                        p.ShiftID = wShiftID;
                    }
                });
            } else if (wTask.Status == 100) {
                wTask.StatusText = wTask.StatusText.replace("待(B级)配送班确认,", "");
                wTask.StatusText = wTask.StatusText.replace("待(B级)作业人员确认,", "");
                wTask.ConfirmedLevels += "B";
                wTask.SFCBOMTaskItemList.forEach(p -> {
                    p.NotSend = StringUtils.isNotEmpty(p.ShiftID);
                    if (p.Level == 2 && p.Status != 2) {
                        p.ShiftID = wShiftID;
                    }
                });
            } else if (wTask.Status == 155) {
                wTask.StatusText = wTask.StatusText.replace("待(A级)配送班确认,", "");
                wTask.StatusText = wTask.StatusText.replace("待(A级)作业人员确认,", "");
                wTask.ConfirmedLevels += "A";
                wTask.SFCBOMTaskItemList.forEach(p -> {
                    p.NotSend = StringUtils.isNotEmpty(p.ShiftID);
                    if (p.Level == 1 && p.Status != 2) {
                        p.ShiftID = wShiftID;
                    }
                });
            }

            // 驳回后修改子项物料状态
            if (wTask.Status == 31) {
                wTask.SFCBOMTaskItemList.forEach(p -> {
                    if (p.Level == 1) {
                        p.Status = 2;
                    }
                });
            } else if (wTask.Status == 32) {
                wTask.SFCBOMTaskItemList.forEach(p -> {
                    if (p.Level == 2) {
                        p.Status = 2;
                    }
                });
            } else if (wTask.Status == 33) {
                wTask.SFCBOMTaskItemList.forEach(p -> {
                    if (p.Level == 3) {
                        p.Status = 2;
                    }
                });
            }

            // 获取真实的状态文本，参考流程引擎
            List<BPMActivitiHisTask> wBPMActivitiHisTaskList = BPMServiceImpl.getInstance()
                    .BPM_GetHistoryInstanceByID(wLoginUser, wTask.FlowID).List(BPMActivitiHisTask.class);
            if (wBPMActivitiHisTaskList.stream().anyMatch(p -> p.Status == 0)) {
                List<BPMActivitiHisTask> wToDoList = wBPMActivitiHisTaskList.stream().filter(p -> p.Status == 0)
                        .collect(Collectors.toList());
                List<String> wNameList = wToDoList.stream().map(p -> "待" + p.Name).collect(Collectors.toList());
                wTask.StatusText = StringUtils.Join(",", wNameList);
            }

            wResult.Result = (SFCBOMTask) SFCBOMTaskDAO.getInstance().BPM_UpdateTask(wLoginUser, wTask, wErrorCode);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());

            // ①推送物料到SAP
            if (wTask.Status == SFCBOMTaskStatus.NomalClose.getValue() && wTask.MaterialID > 0) {
                OMSOrder wOMSOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wTask.OrderID, wErrorCode);

                APSBOMItem wAPSBOMItem = CreateAPSBOMItem(wLoginUser, wTask, wErrorCode, wOMSOrder);

                APSServiceImpl.getInstance().APS_UpdateBOMItem(wLoginUser, wAPSBOMItem);

            }

            // ①推送物料到SAP(批量子表数据)
            if (wTask.Status == 66) {
                List<SFCBOMTaskItem> wItemList = wTask.SFCBOMTaskItemList.stream()
                        .filter(p -> p.Level == 3 && p.Status != 2).collect(Collectors.toList());
                SynchronizedToSap(wLoginUser, wTask, wErrorCode, wItemList);
            } else if (wTask.Status == 100) {
                List<SFCBOMTaskItem> wItemList = wTask.SFCBOMTaskItemList.stream()
                        .filter(p -> p.Level == 2 && p.Status != 2).collect(Collectors.toList());
                SynchronizedToSap(wLoginUser, wTask, wErrorCode, wItemList);
            } else if (wTask.Status == 155) {
                List<SFCBOMTaskItem> wItemList = wTask.SFCBOMTaskItemList.stream()
                        .filter(p -> p.Level == 1 && p.Status != 2).collect(Collectors.toList());
                SynchronizedToSap(wLoginUser, wTask, wErrorCode, wItemList);
            } else if (wTask.Status == 985) {
                // 推送erp，线边库消耗，erp过账
                List<SFCBOMTaskItem> wItemList = wTask.SFCBOMTaskItemList.stream()
                        .filter(p -> p.Status != 2).collect(Collectors.toList());
                SynchronizedToSap(wLoginUser, wTask, wErrorCode, wItemList);
            } else if (wTask.Status == 211) {
                // 推送erp，线边库消耗，erp过账
                List<SFCBOMTaskItem> wItemList = wTask.SFCBOMTaskItemList.stream()
                        .filter(p -> p.Status != 2).collect(Collectors.toList());
                SynchronizedToSap(wLoginUser, wTask, wErrorCode, wItemList);
            }

            // ①物料自动评级触发
            if (wTask.Status == 3) {
                ExecutorService wES = Executors.newFixedThreadPool(1);
                wES.submit(() -> MaterialAutomaticRating(wTask));
                wES.shutdown();
            }

            // ②物料等级回写
            if (wTask.Status == 4) {
                ExecutorService wES = Executors.newFixedThreadPool(1);
                wES.submit(() -> MaterialLevelBackWrite(wTask));
                wES.shutdown();
            }

            // ③配送班自动确认
            DeliveryConfirm(wTask);
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    /**
     * 物料等级自动回写
     */
    private void MaterialLevelBackWrite(SFCBOMTask wTask) {
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            // ①遍历子项，依次查询等级，并保存
            for (SFCBOMTaskItem wSFCBOMTaskItem : wTask.SFCBOMTaskItemList) {
                int wLevel = SFCBOMTaskDAO.getInstance().SFC_QueryLevelByMaterialID(BaseDAO.SysAdmin,
                        wSFCBOMTaskItem.MaterialID, wErrorCode);
                if (wLevel > 0) {
                    continue;
                }

                SFCBOMTaskDAO.getInstance().SFC_UpdateMaterialLevel(BaseDAO.SysAdmin, wSFCBOMTaskItem.Level,
                        wSFCBOMTaskItem.MaterialID, wErrorCode);
                // 维护维修等级
                int wWXLevel = 0;
                if (wSFCBOMTaskItem.Level == 1 || wSFCBOMTaskItem.Level == 2) {
                    wWXLevel = 2;
                } else if (wSFCBOMTaskItem.Level == 3) {
                    wWXLevel = 3;
                }
                SFCBOMTaskDAO.getInstance().SFC_UpdateMaterialWXLevel(BaseDAO.SysAdmin, wWXLevel,
                        wSFCBOMTaskItem.MaterialID, wErrorCode);
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    /**
     * 物料自动评级
     */
    private void MaterialAutomaticRating(SFCBOMTask wTask) {
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            // ①遍历子项，依次查询等级，并保存
            for (SFCBOMTaskItem wSFCBOMTaskItem : wTask.SFCBOMTaskItemList) {
                int wLevel = SFCBOMTaskDAO.getInstance().SFC_QueryLevelByMaterialID(BaseDAO.SysAdmin,
                        wSFCBOMTaskItem.MaterialID, wErrorCode);
                if (wLevel <= 0) {
                    continue;
                }
                wSFCBOMTaskItem.Level = wLevel;
                // 若评审结果为送修且物料等级为A，则按照维修等级B来处理
                if (wSFCBOMTaskItem.ReviewComments == SFCBOMTaskReviewComments.Repair.getValue() && wLevel == 1) {
                    wSFCBOMTaskItem.Level = 2;
                }
                SFCBOMTaskItemDAO.getInstance().Update(BaseDAO.SysAdmin, wSFCBOMTaskItem, wErrorCode);
            }
            // ②判断，若存在没有等级的物料，返回不处理
            if (wTask.SFCBOMTaskItemList.stream().anyMatch(p -> p.Level <= 0)) {
                return;
            }
            // ③LevelA、LevelB、LevelC赋值
            if (wTask.SFCBOMTaskItemList.stream().anyMatch(p -> p.Level == 1)) {
                wTask.LevelA = true;
            }
            if (wTask.SFCBOMTaskItemList.stream().anyMatch(p -> p.Level == 2)) {
                wTask.LevelB = true;
            }
            if (wTask.SFCBOMTaskItemList.stream().anyMatch(p -> p.Level == 3)) {
                wTask.LevelC = true;
            }
            // ④完成任务节点
            wTask.Status = 4;

            List<BPMActivitiHisTask> wNewTaskList = BPMServiceImpl.getInstance()
                    .BPM_GetHistoryInstanceByID(BaseDAO.SysAdmin, wTask.FlowID).List(BPMActivitiHisTask.class);
            wNewTaskList = wNewTaskList.stream().filter(p -> p.Status == 0).collect(Collectors.toList());

            CoreServiceImpl.getInstance().QMS_CompleteInstance(BaseDAO.SysAdmin, wTask, wNewTaskList.get(0).ID)
                    .Info(SFCBOMTask.class);
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    /**
     * 配送班自动确认
     */
    @Async
    private void DeliveryConfirm(SFCBOMTask wTask) {
        try {
            //若配送单状态不包含`配送班确认`，则不处理
            if (wTask.StatusText.contains("配送班确认") == false) {
                return;
            }

            // 遍历子项，一次判断评估类型并保存
            for (SFCBOMTaskItem wSFCBOMTaskItem : wTask.SFCBOMTaskItemList) {
                if (wSFCBOMTaskItem.ReviewComments == SFCBOMTaskReviewComments.Repair.getValue()) {
                    wSFCBOMTaskItem.SapType = SFCBOMTaskSAPType.XFJJ.getValue();
                } else if (wSFCBOMTaskItem.ReviewComments > 0) {
                    wSFCBOMTaskItem.SapType = SFCBOMTaskSAPType.CGXJ.getValue();
                } else {
                    wSFCBOMTaskItem.SapType = SFCBOMTaskSAPType.Default.getValue();
                }
                SFCBOMTaskItemDAO.getInstance().Update(BaseDAO.SysAdmin, wSFCBOMTaskItem, new OutResult<>(0));
            }
            // 根据配送单状态文本，判断后续应该给的status
            if (wTask.StatusText.contains("(C级)配送班确认")) {
                wTask.Status = 66;
            } else if (wTask.StatusText.contains("(B级)配送班确认")) {
                wTask.Status = 100;
            } else if (wTask.StatusText.contains("(A级)配送班确认")) {
                wTask.Status = 155;
            } else if (wTask.StatusText.contains("配送班确认")) {
                wTask.Status = 985;
            }
            // 筛选任务
            List<BPMActivitiHisTask> wNewTaskList = BPMServiceImpl.getInstance()
                    .BPM_GetHistoryInstanceByID(BaseDAO.SysAdmin, wTask.FlowID).List(BPMActivitiHisTask.class);
            wNewTaskList = wNewTaskList.stream().filter(p -> p.Status == 0 && p.Name.contains("配送班确认")).collect(Collectors.toList());
            if (wNewTaskList.size() > 0) {
                CoreServiceImpl.getInstance().QMS_CompleteInstance(BaseDAO.SysAdmin, wTask, wNewTaskList.get(0).ID)
                        .Info(SFCBOMTask.class);
            } else {
                logger.error("自动确认失败：配送班确认任务不存在");
            }
        } catch (Exception ex) {
            logger.error("DeliveryConfirm", ex);
        }
    }

    /**
     * 保存物料历史记录
     */
    private void SaveMaterialHistory(BMSEmployee wLoginUser, SFCBOMTask wTask) {
        try {
            if (wTask.SFCBOMTaskItemList == null || wTask.SFCBOMTaskItemList.size() <= 0
                    || wTask.SFCBOMTaskItemList.stream().allMatch(p -> p.BOMItemID > 0)) {
                return;
            }

            OutResult<Integer> wErrorCode = new OutResult<>(0);

            List<SFCBOMTaskItem> wList = wTask.SFCBOMTaskItemList.stream().filter(p -> p.BOMItemID <= 0)
                    .collect(Collectors.toList());
            for (SFCBOMTaskItem wSFCBOMTaskItem : wList) {
                List<MSSBOMItemHistory> wSavedList = MSSBOMItemHistoryDAO.getInstance().SelectList(wLoginUser, -1,
                        wTask.ProductID, wTask.LineID, wTask.CustomerID, wTask.PartID, wTask.PartPointID,
                        wSFCBOMTaskItem.MaterialID, wErrorCode);
                if (wSavedList != null && wSavedList.size() > 0) {
                    continue;
                }

                // 查询物料
                MSSMaterial wMaterial = APSBOMItemDAO.getInstance().GetMaterialByID(wLoginUser,
                        wSFCBOMTaskItem.MaterialID, wErrorCode);

                MSSBOMItemHistory wHistory = new MSSBOMItemHistory(0, wTask.ProductID, wTask.LineID, wTask.CustomerID,
                        wTask.PartID, wTask.PartPointID, wSFCBOMTaskItem.MaterialID, wMaterial.MaterialNo,
                        wMaterial.MaterialName, 0, wSFCBOMTaskItem.UnitID, wSFCBOMTaskItem.UnitText);
                MSSBOMItemHistoryDAO.getInstance().Update(wLoginUser, wHistory, wErrorCode);
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    private void SynchronizedToSap(BMSEmployee wLoginUser, SFCBOMTask wTask, OutResult<Integer> wErrorCode,
                                   List<SFCBOMTaskItem> wItemList) {
        try {
            OMSOrder wOMSOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wTask.OrderID, wErrorCode);
            // 移除已确认的单据
            wItemList.removeIf(p -> p.NotSend);
            if (wItemList.size() <= 0) {
                return;
            }

            List<APSBOMItem> wList = CreateAPSBOMItemList(wLoginUser, wTask, wErrorCode, wOMSOrder, wItemList);

            if (wList.size() > 0) {
                ExecutorService wES = Executors.newFixedThreadPool(1);
                wES.submit(() -> APSServiceImpl.getInstance().APS_UpdateBOMItemList(wLoginUser, wList, wTask.ID,
                        wTask.CovaType, wItemList));
                wES.shutdown();
            }

        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    private void SynchronizedToSap(BMSEmployee wLoginUser, SFCScrapApprovalBPM wTask, OutResult<Integer> wErrorCode,
                                   List<SFCScrapApprovalBPMItem> wItemList) {
        try {
            OMSOrder wOMSOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wTask.OrderID, wErrorCode);
            // 移除已确认的单据
            wItemList.removeIf(p -> p.NotSend);

            List<APSBOMItem> wList = CreateAPSBOMItemList(wLoginUser, wTask, wErrorCode, wOMSOrder, wItemList);

            if (wList.size() > 0) {
                ExecutorService wES = Executors.newFixedThreadPool(1);
                wES.submit(() -> APSServiceImpl.getInstance().APS_UpdateBOMItemList(wLoginUser, wList, wTask.ID,
                        wItemList));
                wES.shutdown();
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    private void SynchronizedToSap(BMSEmployee wLoginUser, SFCQualityLossBPM wTask, OutResult<Integer> wErrorCode,
                                   List<SFCQualityLossBPMItem> wItemList) {
        try {
            OMSOrder wOMSOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wTask.OrderID, wErrorCode);
            // 移除已确认的单据
            wItemList.removeIf(p -> p.NotSend);

            List<APSBOMItem> wList = CreateAPSBOMItemList(wLoginUser, wTask, wErrorCode, wOMSOrder, wItemList);

            if (wList.size() > 0) {
                ExecutorService wES = Executors.newFixedThreadPool(1);
                wES.submit(() -> APSServiceImpl.getInstance().APS_UpdateBOMItemListByQualityLoss(wLoginUser, wList,
                        wTask.ID,
                        0, wItemList));
                wES.shutdown();
            }

        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    /**
     * 创建台车bom集合
     */
    private List<APSBOMItem> CreateAPSBOMItemList(BMSEmployee wLoginUser, SFCBOMTask wTask,
                                                  OutResult<Integer> wErrorCode, OMSOrder wOMSOrder,
                                                  List<SFCBOMTaskItem> wItemList) {
        List<APSBOMItem> wResult = new ArrayList<>();
        try {
            if (wItemList == null || wItemList.size() <= 0) {
                return wResult;
            }

            for (SFCBOMTaskItem wSFCBOMTaskItem : wItemList) {
                APSBOMItem wAPSBOMItem;

                int wOutSourceType = 0;
                int wReplaceType = 0;
                int wCustomerMaterial = 0;
                if (wSFCBOMTaskItem.BOMItemID > 0) {
                    // 提交到Core偶换件
                    MSSBOMItem wItem = WMSServiceImpl.getInstance()
                            .MSS_QueryBOMItemByID(wLoginUser, wSFCBOMTaskItem.BOMItemID).Info(MSSBOMItem.class);
                    wOutSourceType = wItem.OutsourceType;
                    wReplaceType = wItem.ReplaceType;
                    wCustomerMaterial = wItem.CSMIdent;
                }
                wAPSBOMItem = new APSBOMItem();
                wAPSBOMItem.ID = 0;
                wAPSBOMItem.BOMType = 2;
                wAPSBOMItem.FactoryID = 1900;
                wAPSBOMItem.WBSNo = wOMSOrder.OrderNo;
                wAPSBOMItem.OrderID = wOMSOrder.ID;
                wAPSBOMItem.PartNo = wOMSOrder.PartNo;
                wAPSBOMItem.LineID = wOMSOrder.LineID;
                wAPSBOMItem.ProductID = wOMSOrder.ProductID;
                wAPSBOMItem.CustomerID = wOMSOrder.CustomerID;
                wAPSBOMItem.PartID = wTask.PartID;
                wAPSBOMItem.PartPointID = wTask.PartPointID;
                wAPSBOMItem.MaterialID = wSFCBOMTaskItem.MaterialID;
                wAPSBOMItem.MaterialNo = wSFCBOMTaskItem.MaterialNo;
                wAPSBOMItem.MaterialName = wSFCBOMTaskItem.MaterialName;
                wAPSBOMItem.Number = wSFCBOMTaskItem.MaterialNumber;
                wAPSBOMItem.UnitID = APSBOMItemDAO.getInstance().GetUnitID(wLoginUser, wSFCBOMTaskItem.MaterialID,
                        wErrorCode);
                wAPSBOMItem.ReplaceType = 2;
                if (wReplaceType > 0) {
                    wAPSBOMItem.ReplaceType = wReplaceType;
                }
                wAPSBOMItem.OutsourceType = wOutSourceType;
                // 若是委外偶修件，需设置为互换件
                if (wOutSourceType == 2) {
                    wAPSBOMItem.PartChange = 1;
                }
                wAPSBOMItem.StockID = 1200;
                wAPSBOMItem.Status = 1;
                wAPSBOMItem.CustomerMaterial = wCustomerMaterial;

                if (wSFCBOMTaskItem.SapType == 1) {
                    wAPSBOMItem.AssessmentType = "常规新件";
                } else if (wSFCBOMTaskItem.SapType == 2) {
                    wAPSBOMItem.AssessmentType = "修复旧件";
                } else if (wSFCBOMTaskItem.SapType == 3) {
                    wAPSBOMItem.AssessmentType = "可用旧件";
                } else if (wSFCBOMTaskItem.SapType == 4) {
                    wAPSBOMItem.AssessmentType = "高价互换件";
                }
                wAPSBOMItem.SourceType = APSBOMSourceType.SFCBOMTask.getValue();
                wAPSBOMItem.SourceID = wSFCBOMTaskItem.ID;
                wAPSBOMItem.AuditTime = Calendar.getInstance();
                wAPSBOMItem.EditTime = Calendar.getInstance();

                wAPSBOMItem.NewSourceID = wTask.ID;
                wAPSBOMItem.NewSourceCode = wTask.Code;
                wAPSBOMItem.ReviewComments = wSFCBOMTaskItem.ReviewComments;

                // ①加入质量损失
                if (StringUtils.isNotEmpty(wSFCBOMTaskItem.QualityLossBig)
                        || StringUtils.isNotEmpty(wSFCBOMTaskItem.QualityLossSmall)) {
                    wAPSBOMItem.BOMType = 9;
                    wAPSBOMItem.QTType = GetQTType(wSFCBOMTaskItem.QualityLossBig);
                    wAPSBOMItem.QTItemType = GetQTItemType(wSFCBOMTaskItem.QualityLossSmall);
                }

                wResult.add(wAPSBOMItem);
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
        return wResult;
    }

    /**
     * 创建台车bom集合
     */
    private List<APSBOMItem> CreateAPSBOMItemList(BMSEmployee wLoginUser, SFCScrapApprovalBPM wTask,
                                                  OutResult<Integer> wErrorCode, OMSOrder wOMSOrder,
                                                  List<SFCScrapApprovalBPMItem> wItemList) {
        List<APSBOMItem> wResult = new ArrayList<>();
        try {
            if (wItemList == null || wItemList.size() <= 0) {
                return wResult;
            }

            for (SFCScrapApprovalBPMItem wSFCBOMTaskItem : wItemList) {
                APSBOMItem wAPSBOMItem;

                int wOutSourceType = 0;
                int wReplaceType = 0;
                if (wSFCBOMTaskItem.BOMItemID > 0) {
                    // 提交到Core偶换件
                    MSSBOMItem wItem = WMSServiceImpl.getInstance()
                            .MSS_QueryBOMItemByID(wLoginUser, wSFCBOMTaskItem.BOMItemID).Info(MSSBOMItem.class);
                    wOutSourceType = wItem.OutsourceType;
                    wReplaceType = wItem.ReplaceType;
                }
                wAPSBOMItem = new APSBOMItem();
                wAPSBOMItem.ID = 0;
                wAPSBOMItem.BOMType = 2;
                wAPSBOMItem.FactoryID = 1900;
                wAPSBOMItem.WBSNo = wOMSOrder.OrderNo;
                wAPSBOMItem.OrderID = wOMSOrder.ID;
                wAPSBOMItem.PartNo = wOMSOrder.PartNo;
                wAPSBOMItem.LineID = wOMSOrder.LineID;
                wAPSBOMItem.ProductID = wOMSOrder.ProductID;
                wAPSBOMItem.CustomerID = wOMSOrder.CustomerID;
                wAPSBOMItem.PartID = wTask.PartID;
                wAPSBOMItem.PartPointID = wTask.PartPointID;
                wAPSBOMItem.MaterialID = wSFCBOMTaskItem.MaterialID;
                wAPSBOMItem.MaterialNo = wSFCBOMTaskItem.MaterialNo;
                wAPSBOMItem.MaterialName = wSFCBOMTaskItem.MaterialName;
                wAPSBOMItem.Number = wSFCBOMTaskItem.MaterialNumber;
                wAPSBOMItem.UnitID = APSBOMItemDAO.getInstance().GetUnitID(wLoginUser, wSFCBOMTaskItem.MaterialID,
                        wErrorCode);
                wAPSBOMItem.ReplaceType = 2;
                if (wReplaceType > 0) {
                    wAPSBOMItem.ReplaceType = wReplaceType;
                }
                wAPSBOMItem.OutsourceType = wOutSourceType;
                // 若是委外偶修件，需设置为互换件
                if (wOutSourceType == 2) {
                    wAPSBOMItem.PartChange = 1;
                }
                wAPSBOMItem.StockID = 1200;
                wAPSBOMItem.Status = 1;

                if (wSFCBOMTaskItem.SapType == 1) {
                    wAPSBOMItem.AssessmentType = "常规新件";
                } else if (wSFCBOMTaskItem.SapType == 2) {
                    wAPSBOMItem.AssessmentType = "修复旧件";
                } else if (wSFCBOMTaskItem.SapType == 3) {
                    wAPSBOMItem.AssessmentType = "可用旧件";
                } else if (wSFCBOMTaskItem.SapType == 4) {
                    wAPSBOMItem.AssessmentType = "高价互换件";
                }
                wAPSBOMItem.SourceType = APSBOMSourceType.ScrapApproval.getValue();
                wAPSBOMItem.SourceID = wTask.ID;
                wAPSBOMItem.AuditTime = Calendar.getInstance();
                wAPSBOMItem.EditTime = Calendar.getInstance();

                wAPSBOMItem.NewSourceID = wTask.ID;
                wAPSBOMItem.NewSourceCode = wTask.Code;
                wAPSBOMItem.ReviewComments = wSFCBOMTaskItem.ReviewComments;

                // ①加入质量损失
                if (StringUtils.isNotEmpty(wSFCBOMTaskItem.QualityLossBig)
                        || StringUtils.isNotEmpty(wSFCBOMTaskItem.QualityLossSmall)) {
                    wAPSBOMItem.BOMType = 9;
                    wAPSBOMItem.QTType = GetQTType(wSFCBOMTaskItem.QualityLossBig);
                    wAPSBOMItem.QTItemType = GetQTItemType(wSFCBOMTaskItem.QualityLossSmall);
                }

                wResult.add(wAPSBOMItem);
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
        return wResult;
    }

    /**
     * 创建台车bom集合
     */
    private List<APSBOMItem> CreateAPSBOMItemList(BMSEmployee wLoginUser, SFCQualityLossBPM wTask,
                                                  OutResult<Integer> wErrorCode, OMSOrder wOMSOrder,
                                                  List<SFCQualityLossBPMItem> wItemList) {
        List<APSBOMItem> wResult = new ArrayList<>();
        try {
            if (wItemList == null || wItemList.size() <= 0) {
                return wResult;
            }

            for (SFCQualityLossBPMItem wSFCBOMTaskItem : wItemList) {
                APSBOMItem wAPSBOMItem;

                int wOutSourceType = 0;
                int wReplaceType = 0;
                if (wSFCBOMTaskItem.BOMItemID > 0) {
                    // 提交到Core偶换件
                    MSSBOMItem wItem = WMSServiceImpl.getInstance()
                            .MSS_QueryBOMItemByID(wLoginUser, wSFCBOMTaskItem.BOMItemID).Info(MSSBOMItem.class);
                    wOutSourceType = wItem.OutsourceType;
                    wReplaceType = wItem.ReplaceType;
                }
                wAPSBOMItem = new APSBOMItem();
                wAPSBOMItem.ID = 0;
                wAPSBOMItem.BOMType = 2;
                wAPSBOMItem.FactoryID = 1900;
                wAPSBOMItem.WBSNo = wOMSOrder.OrderNo;
                wAPSBOMItem.OrderID = wOMSOrder.ID;
                wAPSBOMItem.PartNo = wOMSOrder.PartNo;
                wAPSBOMItem.LineID = wOMSOrder.LineID;
                wAPSBOMItem.ProductID = wOMSOrder.ProductID;
                wAPSBOMItem.CustomerID = wOMSOrder.CustomerID;
                wAPSBOMItem.PartID = wTask.PartID;
                wAPSBOMItem.PartPointID = wTask.PartPointID;
                wAPSBOMItem.MaterialID = wSFCBOMTaskItem.MaterialID;
                wAPSBOMItem.MaterialNo = wSFCBOMTaskItem.MaterialNo;
                wAPSBOMItem.MaterialName = wSFCBOMTaskItem.MaterialName;
                wAPSBOMItem.Number = wSFCBOMTaskItem.MaterialNumber;
                wAPSBOMItem.UnitID = APSBOMItemDAO.getInstance().GetUnitID(wLoginUser, wSFCBOMTaskItem.MaterialID,
                        wErrorCode);
                wAPSBOMItem.ReplaceType = 2;
                if (wReplaceType > 0) {
                    wAPSBOMItem.ReplaceType = wReplaceType;
                }
                wAPSBOMItem.OutsourceType = wOutSourceType;
                // 若是委外偶修件，需设置为互换件
                if (wOutSourceType == 2) {
                    wAPSBOMItem.PartChange = 1;
                }
                wAPSBOMItem.StockID = 1200;
                wAPSBOMItem.Status = 1;

                if (wSFCBOMTaskItem.SapType == 1) {
                    wAPSBOMItem.AssessmentType = "常规新件";
                } else if (wSFCBOMTaskItem.SapType == 2) {
                    wAPSBOMItem.AssessmentType = "修复旧件";
                } else if (wSFCBOMTaskItem.SapType == 3) {
                    wAPSBOMItem.AssessmentType = "可用旧件";
                } else if (wSFCBOMTaskItem.SapType == 4) {
                    wAPSBOMItem.AssessmentType = "高价互换件";
                }
                wAPSBOMItem.SourceType = APSBOMSourceType.QualityLoss.getValue();
                wAPSBOMItem.SourceID = wSFCBOMTaskItem.ID;
                wAPSBOMItem.AuditTime = Calendar.getInstance();
                wAPSBOMItem.EditTime = Calendar.getInstance();

                wAPSBOMItem.NewSourceID = wTask.ID;
                wAPSBOMItem.NewSourceCode = wTask.Code;
                wAPSBOMItem.ReviewComments = wSFCBOMTaskItem.ReviewComments;

                // ①加入质量损失
                if (StringUtils.isNotEmpty(wTask.QualityLossBig)
                        || StringUtils.isNotEmpty(wTask.QualityLossSmall)) {
                    wAPSBOMItem.BOMType = 9;
                    wAPSBOMItem.QTType = GetQTType(wTask.QualityLossBig);
                    wAPSBOMItem.QTItemType = GetQTItemType(wTask.QualityLossSmall);
                }

                wResult.add(wAPSBOMItem);
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
        return wResult;
    }

    /**
     * 获取质量损失小类
     */
    private int GetQTItemType(String qualityLossSmall) {
        int wResult = 0;
        try {
            switch (qualityLossSmall) {
                case "1":
                case "01":
                    wResult = 1;
                    break;
                case "2":
                case "02":
                    wResult = 2;
                    break;
                case "3":
                case "03":
                    wResult = 3;
                    break;
                case "4":
                case "04":
                    wResult = 4;
                    break;
                case "5":
                case "05":
                    wResult = 5;
                    break;
                default:
                    break;
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
        return wResult;
    }

    /**
     * 获取质量损失大类
     */
    private int GetQTType(String qualityLossBig) {
        int wResult = 0;
        try {
            switch (qualityLossBig) {
                case "1":
                case "001":
                    wResult = 1;
                    break;
                case "2":
                case "002":
                    wResult = 2;
                    break;
                case "3":
                case "003":
                    wResult = 3;
                    break;
                case "4":
                case "004":
                    wResult = 4;
                    break;
                default:
                    break;
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
        return wResult;
    }

    @SuppressWarnings("unused")
    private APSBOMItem CreateAPSBOMItem(BMSEmployee wLoginUser, SFCBOMTask wTask, OutResult<Integer> wErrorCode,
                                        OMSOrder wOMSOrder) {
        APSBOMItem wAPSBOMItem = null;
        try {
            if (wTask.BOMItemID > 0) {
                // 提交到Core偶换件
                MSSBOMItem wItem = WMSServiceImpl.getInstance().MSS_QueryBOMItemByID(wLoginUser, wTask.BOMItemID)
                        .Info(MSSBOMItem.class);
                wItem.MaterialNumber = wTask.MaterialNumber;
                wAPSBOMItem = new APSBOMItem(wItem, wOMSOrder.LineID, wOMSOrder.ProductID, wOMSOrder.BureauSectionID,
                        wOMSOrder.ID, wOMSOrder.OrderNo, wOMSOrder.PartNo);
            } else {
                wAPSBOMItem = new APSBOMItem();
                wAPSBOMItem.ID = 0;
                wAPSBOMItem.BOMType = 2;
                wAPSBOMItem.FactoryID = 1900;
                wAPSBOMItem.WBSNo = wOMSOrder.OrderNo;
                wAPSBOMItem.OrderID = wOMSOrder.ID;
                wAPSBOMItem.PartNo = wOMSOrder.PartNo;
                wAPSBOMItem.LineID = wOMSOrder.LineID;
                wAPSBOMItem.ProductID = wOMSOrder.ProductID;
                wAPSBOMItem.CustomerID = wOMSOrder.CustomerID;
                wAPSBOMItem.PartID = wTask.PartID;
                wAPSBOMItem.PartPointID = wTask.PartPointID;
                wAPSBOMItem.MaterialID = wTask.MaterialID;
                wAPSBOMItem.MaterialNo = wTask.MaterialNo;
                wAPSBOMItem.Number = wTask.MaterialNumber;
                wAPSBOMItem.UnitID = APSBOMItemDAO.getInstance().GetUnitID(wLoginUser, wTask.MaterialID, wErrorCode);
                wAPSBOMItem.ReplaceType = 2;
                wAPSBOMItem.StockID = 1200;
                wAPSBOMItem.Status = 1;
            }

            if (wTask.SapType == 1) {
                wAPSBOMItem.AssessmentType = "常规新件";
            } else if (wTask.SapType == 2) {
                wAPSBOMItem.AssessmentType = "修复旧件";
            }
            wAPSBOMItem.SourceType = APSBOMSourceType.SFCBOMTask.getValue();
            wAPSBOMItem.SourceID = wTask.ID;
            wAPSBOMItem.AuditTime = Calendar.getInstance();
            wAPSBOMItem.EditTime = Calendar.getInstance();
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
        return wAPSBOMItem;
    }

    /**
     * 划分等级、处理单据
     */
    @SuppressWarnings("unused")
    private void LevelHandle(BMSEmployee wLoginUser, SFCBOMTask wTask, OutResult<Integer> wErrorCode) {
        try {
            if (wTask.Status != 50) {
                return;
            }

            if (wTask.SFCBOMTaskItemList == null || wTask.SFCBOMTaskItemList.size() <= 0) {
                return;
            }

            if (wTask.SFCBOMTaskItemList.stream().allMatch(p -> p.Level == 1)
                    || wTask.SFCBOMTaskItemList.stream().allMatch(p -> p.Level == 2)
                    || wTask.SFCBOMTaskItemList.stream().allMatch(p -> p.Level == 3)) {
                return;
            }

            // A等级
            List<SFCBOMTaskItem> wAList = wTask.SFCBOMTaskItemList.stream().filter(p -> p.Level == 1)
                    .collect(Collectors.toList());
            // B等级
            List<SFCBOMTaskItem> wBList = wTask.SFCBOMTaskItemList.stream().filter(p -> p.Level == 2)
                    .collect(Collectors.toList());
            // C等级
            List<SFCBOMTaskItem> wCList = wTask.SFCBOMTaskItemList.stream().filter(p -> p.Level == 3)
                    .collect(Collectors.toList());

            // ①A等级有数据
            if (wAList.size() > 0) {
                // ②删除老单据的子项数据
                SFCBOMTaskItemDAO.getInstance().DeleteList(wLoginUser, wTask.SFCBOMTaskItemList, wErrorCode);

                // 保存子项
                for (SFCBOMTaskItem wItem : wAList) {
                    wItem.ID = 0;
                    wItem.SFCBOMTaskID = wTask.ID;
                    SFCBOMTaskItemDAO.getInstance().Update(wLoginUser, wItem, wErrorCode);
                }

                wTask.SFCBOMTaskItemList = wAList;
                wTask.Level = 1;
                if (wBList.size() > 0) {
                    CopyProcess(wLoginUser, wBList, wTask, 2, wErrorCode);
                }
                if (wCList.size() > 0) {
                    CopyProcess(wLoginUser, wCList, wTask, 3, wErrorCode);
                }
            } else {
                // ②删除老单据的子项数据
                SFCBOMTaskItemDAO.getInstance().DeleteList(wLoginUser, wTask.SFCBOMTaskItemList, wErrorCode);
                // ②A等级没数据
                wTask.SFCBOMTaskItemList = wBList;

                // 保存子项
                for (SFCBOMTaskItem wItem : wBList) {
                    wItem.ID = 0;
                    wItem.SFCBOMTaskID = wTask.ID;
                    SFCBOMTaskItemDAO.getInstance().Update(wLoginUser, wItem, wErrorCode);
                }

                wTask.Level = 2;
                if (wCList.size() > 0) {
                    CopyProcess(wLoginUser, wCList, wTask, 3, wErrorCode);
                }
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    /**
     * 复制单据流程到评级后
     */
    private void CopyProcess(BMSEmployee wLoginUser, List<SFCBOMTaskItem> wList, SFCBOMTask wTask, int wLevel,
                             OutResult<Integer> wErrorCode) {
        try {
            // ①查询历史记录
            List<BPMActivitiHisTask> wHisList = BPMServiceImpl.getInstance()
                    .BPM_GetHistoryInstanceByID(wLoginUser, wTask.FlowID).List(BPMActivitiHisTask.class);
            wHisList.removeIf(p -> p.Status == 0);
            // ①发起

            BMSEmployee wUser = CloneTool.Clone(APSConstans.GetBMSEmployee(wTask.UpFlowID), BMSEmployee.class);
            wUser.LoginName = DesUtil.encrypt(wUser.LoginName, BaseDAO.appSecret);
            wUser.Password = DesUtil.encrypt("123456", BaseDAO.appSecret);

            APIResult wAPiResult = CoreServiceImpl.getInstance().QMS_StartInstance(wUser, "8201");
            List<BPMActivitiTask> wBPMActivitiTask = wAPiResult.List(BPMActivitiTask.class);
            SFCBOMTask wData = wAPiResult.Custom("data", SFCBOMTask.class);

            SFCBOMTask wCloneItem = CloneTool.Clone(wTask, SFCBOMTask.class);

            wCloneItem.SFCBOMTaskItemList = wList;

            wCloneItem.ID = wData.ID;
            wCloneItem.Code = wData.Code;
            wCloneItem.Status = 14;
            wCloneItem.FlowID = wData.FlowID;
            wCloneItem.AreaCharge = wHisList.get(1).Assignee;
            wCloneItem.Level = wLevel;

            wCloneItem = CoreServiceImpl.getInstance()
                    .QMS_CompleteInstance(wUser, wCloneItem, wBPMActivitiTask.get(0).ID).Info(SFCBOMTask.class);

            // 保存子项
            for (SFCBOMTaskItem wItem : wList) {
                wItem.ID = 0;
                wItem.SFCBOMTaskID = wCloneItem.ID;
                SFCBOMTaskItemDAO.getInstance().Update(wLoginUser, wItem, wErrorCode);
            }

            // ①处理1

            wUser = CloneTool.Clone(APSConstans.GetBMSEmployee(Integer.parseInt(wHisList.get(1).Assignee)),
                    BMSEmployee.class);
            wUser.LoginName = DesUtil.encrypt(wUser.LoginName, BaseDAO.appSecret);
            wUser.Password = DesUtil.encrypt("123456", BaseDAO.appSecret);

            wCloneItem.Status = 25;

            List<BPMActivitiHisTask> wNewTaskList = BPMServiceImpl.getInstance()
                    .BPM_GetHistoryInstanceByID(wLoginUser, wCloneItem.FlowID).List(BPMActivitiHisTask.class);
            wNewTaskList = wNewTaskList.stream().filter(p -> p.Status == 0).collect(Collectors.toList());

            wCloneItem = CoreServiceImpl.getInstance().QMS_CompleteInstance(wUser, wCloneItem, wNewTaskList.get(0).ID)
                    .Info(SFCBOMTask.class);

            // ①处理2
            wUser = CloneTool.Clone(APSConstans.GetBMSEmployee(Integer.parseInt(wHisList.get(2).Assignee)),
                    BMSEmployee.class);
            wUser.LoginName = DesUtil.encrypt(wUser.LoginName, BaseDAO.appSecret);
            wUser.Password = DesUtil.encrypt("123456", BaseDAO.appSecret);

            wCloneItem.Status = 1;

            wNewTaskList = BPMServiceImpl.getInstance().BPM_GetHistoryInstanceByID(wLoginUser, wCloneItem.FlowID)
                    .List(BPMActivitiHisTask.class);
            wNewTaskList = wNewTaskList.stream().filter(p -> p.Status == 0).collect(Collectors.toList());

            wCloneItem = CoreServiceImpl.getInstance().QMS_CompleteInstance(wUser, wCloneItem, wNewTaskList.get(0).ID)
                    .Info(SFCBOMTask.class);

            // ①处理3
            wUser = CloneTool.Clone(APSConstans.GetBMSEmployee(Integer.parseInt(wHisList.get(3).Assignee)),
                    BMSEmployee.class);
            wUser.LoginName = DesUtil.encrypt(wUser.LoginName, BaseDAO.appSecret);
            wUser.Password = DesUtil.encrypt("123456", BaseDAO.appSecret);

            wCloneItem.Status = 50;

            wNewTaskList = BPMServiceImpl.getInstance().BPM_GetHistoryInstanceByID(wLoginUser, wCloneItem.FlowID)
                    .List(BPMActivitiHisTask.class);
            wNewTaskList = wNewTaskList.stream().filter(p -> p.Status == 0).collect(Collectors.toList());

            CoreServiceImpl.getInstance().QMS_CompleteInstance(wUser, wCloneItem, wNewTaskList.get(0).ID)
                    .Info(SFCBOMTask.class);
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    @Override
    public ServiceResult<SFCBOMTask> SFC_QueryDefaultBOMTask(BMSEmployee wLoginUser, int wEventID) {
        ServiceResult<SFCBOMTask> wResult = new ServiceResult<>();
        wResult.Result = new SFCBOMTask();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            List<SFCBOMTask> wList = SFCBOMTaskDAO.getInstance().SelectList(wLoginUser, -1, "", wLoginUser.ID, "", -1,
                    -1, -1, -1, -1, new ArrayList<>(Collections.singletonList(0)), null, null, wErrorCode);
            if (wList != null && wList.size() > 0) {
                wResult.Result = wList.get(0);
                wResult.Result.VersionNo = "1.0";
            }
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public synchronized ServiceResult<SFCBOMTask> SFC_CreateBOMTask(BMSEmployee wLoginUser, BPMEventModule wEventID) {
        ServiceResult<SFCBOMTask> wResult = new ServiceResult<>();
        wResult.Result = new SFCBOMTask();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            SFCBOMTask wItem = new SFCBOMTask();
            wItem.ID = 0;
            wItem.Code = SFCBOMTaskDAO.getInstance().GetNewCode(wLoginUser, wErrorCode);
            wItem.UpFlowID = wLoginUser.ID;
            wItem.UpFlowName = wLoginUser.Name;
            wItem.FlowType = BPMEventModule.OccasionNCR.getValue();
            wItem.Status = 0;
            wItem.Level = NCRLevel.Default.getValue();
            wItem.CreateTime = Calendar.getInstance();
            wItem.SubmitTime = Calendar.getInstance();
            wItem.Responsibility = 0;
            wItem.ReviewComments = 0;
            wItem.VersionNo = "1.0";
            wResult.Result = (SFCBOMTask) SFCBOMTaskDAO.getInstance().BPM_UpdateTask(wLoginUser, wItem, wErrorCode);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<SFCBOMTask> SFC_GetBOMTask(BMSEmployee wLoginUser, int wID) {
        ServiceResult<SFCBOMTask> wResult = new ServiceResult<>();
        wResult.Result = new SFCBOMTask();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            wResult.Result = (SFCBOMTask) SFCBOMTaskDAO.getInstance().BPM_GetTaskInfo(wLoginUser, wID, "", wErrorCode);

            // bug任务转发
            if (wResult.Result.ID > 0) {
                List<BPMActivitiHisTask> list = BPMServiceImpl.getInstance().BPM_GetActivitiHisTaskByPIId(wLoginUser,
                        wResult.Result.FlowID).List(BPMActivitiHisTask.class);
                Optional<BPMActivitiHisTask> wOption = list.stream().filter(p -> p.Status == 0 && p.Name.equals(
                        "工艺人员填写处理意见") && p.Assignee.equals("-100")).findFirst();
                if (wOption.isPresent()) {
                    BPMActivitiHisTask bpmActivitiHisTask = wOption.get();
                    // 转发给指定工艺师
                    if (StringUtils.isNotEmpty(wResult.Result.CraftsmanIDs)) {
                        BPMServiceImpl.getInstance().BPM_DelegateTask(BaseDAO.SysAdmin, bpmActivitiHisTask.ID,
                                wResult.Result.CraftsmanIDs, "");
                    }
                }
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<SFCStationPerson> SFC_QueryStationPerson(BMSEmployee wLoginUser, int wStationID) {
        ServiceResult<SFCStationPerson> wResult = new ServiceResult<>();
        wResult.Result = new SFCStationPerson();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            // ①获取工区工位列表
            List<LFSWorkAreaStation> wASList = APSConstans.GetLFSWorkAreaStationList().values().stream()
                    .filter(p -> p.Active == 1 && p.StationID == wStationID).collect(Collectors.toList());
            // ②获取班组工位列表
            List<FMCWorkCharge> wWCList = APSConstans.GetFMCWorkChargeList().stream()
                    .filter(p -> p.Active == 1 && p.StationID == wStationID).collect(Collectors.toList());
            // ①获取工区主管
            List<LFSWorkAreaChecker> wWorkCheckerList = APSConstans.GetLFSWorkAreaCheckerList();
            if (wASList.size() > 0) {
                wResult.Result.AreaID = wASList.get(0).WorkAreaID;
                wResult.Result.AreaName = wASList.get(0).WorkArea;
                if (wWorkCheckerList.stream()
                        .anyMatch(p -> p.WorkAreaID == wResult.Result.AreaID && p.WorkAreaID > 0)) {
                    LFSWorkAreaChecker wChecker = wWorkCheckerList.stream()
                            .filter(p -> p.WorkAreaID == wResult.Result.AreaID).findFirst().get();
                    wResult.Result.AuditorList = wChecker.LeaderIDList;
                    if (wChecker.LeaderIDList != null && wChecker.LeaderIDList.size() > 0) {
                        wResult.Result.Auditors = this.GetNames(wChecker.LeaderIDList);
                    }
                }
            }

            // 工区主管(一个工位，三个班组，最多获取到三个主管，然后通过登录人获取主管，若在三个主管中，取登录人的主管，若不在，返回工位负责的所有主管)
            SetAuditors(wLoginUser, wResult, wErrorCode, wWCList, wWorkCheckerList);

            // ①获取工艺师
            if (wWCList.size() > 0) {
                wResult.Result.TechnicianList = APSUtils.getInstance().QueryCraftsman(wLoginUser, -1, wStationID, -1)
                        .stream().map(p -> p.ID).distinct().collect(Collectors.toList());
                wResult.Result.Technicians = StringUtils.Join(",", APSUtils.getInstance().QueryCraftsman(wLoginUser,
                        -1, wStationID, -1).stream().map(p -> p.Name).distinct().collect(Collectors.toList()));
            }
            // 赋值工位
            wResult.Result.StationID = wStationID;
            wResult.Result.StationName = APSConstans.GetFPCPartName(wStationID);

            // 库管工位
            if (wResult.Result.AuditorList == null || wResult.Result.AuditorList.size() <= 0) {
                List<BMSRoleItem> wUList = CoreServiceImpl.getInstance().BMS_UserAllByRoleID(wLoginUser, 24)
                        .List(BMSRoleItem.class);

                wResult.Result.AuditorList = wUList.stream().map(p -> p.FunctionID).distinct()
                        .collect(Collectors.toList());

                wResult.Result.Auditors = GetNames(wResult.Result.AuditorList);
            }
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    /**
     * 设置工区主管
     */
    private void SetAuditors(BMSEmployee wLoginUser, ServiceResult<SFCStationPerson> wResult,
                             OutResult<Integer> wErrorCode, List<FMCWorkCharge> wWCList,
                             List<LFSWorkAreaChecker> wWorkCheckerList) {
        try {
            List<Integer> wAllAuditorList = new ArrayList<>();
            for (FMCWorkCharge wFMCWorkCharge : wWCList) {
                // 根据班组获取工区
                int wAreaID = SFCBOMTaskDAO.getInstance().GetAreaIDByClassID(wLoginUser, wFMCWorkCharge.ClassID,
                        wErrorCode);
                // 根据工区获取工区主管
                if (wAreaID > 0 && wWorkCheckerList.stream().anyMatch(p -> p.WorkAreaID == wAreaID)) {
                    List<Integer> wLList = wWorkCheckerList.stream().filter(p -> p.WorkAreaID == wAreaID).findFirst()
                            .get().LeaderIDList;
                    wAllAuditorList.addAll(wLList);
                }
            }
            wAllAuditorList = wAllAuditorList.stream().distinct().collect(Collectors.toList());
            // 根据登录人获取工区主管
            int wLoginAreaID = SFCBOMTaskDAO.getInstance().GetAreaIDByClassID(wLoginUser, wLoginUser.DepartmentID,
                    wErrorCode);
            if (wLoginAreaID > 0 && wWorkCheckerList.stream().anyMatch(p -> p.WorkAreaID == wLoginAreaID)) {
                List<Integer> wLList = wWorkCheckerList.stream().filter(p -> p.WorkAreaID == wLoginAreaID).findFirst()
                        .get().LeaderIDList;
                List<Integer> wAllAuditorListClone = wAllAuditorList;
                if (wLList.stream().allMatch(p -> wAllAuditorListClone.stream().anyMatch(q -> Objects.equals(q, p)))) {
                    wResult.Result.AuditorList = wLList;
                    wResult.Result.Auditors = this.GetNames(wLList);
                }
            } else {
                wResult.Result.AuditorList = wAllAuditorList;
                wResult.Result.Auditors = this.GetNames(wResult.Result.AuditorList);
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    /**
     * 根据人员ID集合获取名称
     */
    private String GetNames(List<Integer> wIDList) {
        String wResult = "";
        try {
            if (wIDList == null || wIDList.size() <= 0) {
                return wResult;
            }

            List<String> wNames = new ArrayList<>();
            for (Integer wID : wIDList) {
                String wName = APSConstans.GetBMSEmployeeName(wID);
                if (StringUtils.isEmpty(wName)) {
                    continue;
                }
                wNames.add(wName);
            }

            if (wNames.size() > 0) {
                wResult = StringUtils.Join(",", wNames);
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
        return wResult;
    }

    @Override
    public synchronized ServiceResult<Integer> SFC_AddPerson(BMSEmployee wLoginUser, APSTaskStep wData,
                                                             List<Integer> wPersonIDList) {
        ServiceResult<Integer> wResult = new ServiceResult<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            if (wData == null || wData.ID <= 0 || wPersonIDList == null || wPersonIDList.size() <= 0) {
                wResult.FaultCode += "提示：参数错误!";
            }

            if (wPersonIDList != null && wData != null && wData.OperatorList.stream()
                    .anyMatch(p -> wPersonIDList.stream().anyMatch(q -> Objects.equals(q, p)))) {
                wResult.FaultCode += "提示：“开工”状态的任务只能新增操作工不能修改操作工";
                return wResult;
            }

            // 查询已派工人
            List<SFCTaskStep> wSFCTaskStepList = null;
            if (wData != null) {
                wSFCTaskStepList = SFCTaskStepDAO.getInstance().SelectList(wLoginUser, -1, wData.ID, -1,
                        -1, -1, null, -1, wErrorCode);
            }
            if (wPersonIDList != null) {
                List<SFCTaskStep> finalWSFCTaskStepList = wSFCTaskStepList;
                wPersonIDList.removeIf(p -> finalWSFCTaskStepList.stream().anyMatch(q -> q.OperatorID == p));
            }

            // APS
            int wShiftID = MESServer.MES_QueryShiftID(wLoginUser.CompanyID, Calendar.getInstance(), APSShiftPeriod.Day,
                    FMCShiftLevel.Day, 0);
            Calendar wBaseTime = Calendar.getInstance();
            wBaseTime.set(2000, 0, 1);

            List<BFCMessage> wMessageList = new ArrayList<>();
            if (wPersonIDList != null) {
                for (Integer wPersonID : wPersonIDList) {
                    SFCTaskStep wSFCTaskStep = new SFCTaskStep();
                    wSFCTaskStep.TaskStepID = wData.ID;
                    wSFCTaskStep.CreateTime = Calendar.getInstance();
                    wSFCTaskStep.EndTime = wBaseTime;
                    wSFCTaskStep.ShiftID = wShiftID;
                    wSFCTaskStep.WorkHour = 0.0D;
                    wSFCTaskStep.OperatorID = wPersonID;
                    wSFCTaskStep.ReadyTime = Calendar.getInstance();
                    wSFCTaskStep.MonitorID = wLoginUser.ID;
                    wSFCTaskStep.Type = (wData.TaskPartID > 0) ? SFCTaskStepType.Step.getValue()
                            : SFCTaskStepType.Quality.getValue();
                    int wNewID = (SFC_UpdateTaskStep(wLoginUser, wSFCTaskStep)).Result;

                    this.CreateMessage(wLoginUser, wShiftID, wSFCTaskStep, wNewID, wMessageList, wData, wPersonID);
                }
            }
            // 发送消息
            CoreServiceImpl.getInstance().BFC_UpdateMessageList(wLoginUser, wMessageList);
            // 更新工序任务的OperatorList
            if (wData != null) {
                if (wData.OperatorList == null) {
                    wData.OperatorList = wPersonIDList;
                } else {
                    if (wPersonIDList != null) {
                        wData.OperatorList.addAll(wPersonIDList);
                    }
                }
            }
            APSTaskStepDAO.getInstance().Update(wLoginUser, wData, wErrorCode);

            // 判断互检消息是否生成
            ExecutorService wES = Executors.newFixedThreadPool(1);
            wES.submit(() -> GenerateMutualMessage(wLoginUser, wData, wErrorCode));
            wES.shutdown();
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    /**
     * 判断互检消息是否生成，若没有生成，则生成互检消息
     */
    private void GenerateMutualMessage(BMSEmployee wLoginUser, APSTaskStep wData, OutResult<Integer> wErrorCode) {
        try {
            // ①查询未完成的互检单
            int wMutualTaskID = SFCTaskStepDAO.getInstance().QueryMutualTaskID(wLoginUser, wData.ID, wErrorCode);
            if (wMutualTaskID <= 0) {
                return;
            }
            // ②根据互检单查询互检待办消息
            // int wMessageCount =
            // SFCTaskStepDAO.getInstance().QueryMutualMessageCount(wLoginUser,
            // wMutualTaskID,
            // wErrorCode);
            // if (wMessageCount > 0) {
            // return;
            // }
            // ③若没有，查询自检人
            String wSelfOpes = SFCTaskStepDAO.getInstance().QuerySelfOpes(wLoginUser, wData.ID, wErrorCode);
            if (StringUtils.isEmpty(wSelfOpes)) {
                return;
            }
            // ④筛选互检人
            List<SFCTaskStep> wList = SFCTaskStepDAO.getInstance().SelectList(wLoginUser, -1, wData.ID, -1, -1, -1,
                    null, -1, wErrorCode);
            wList.removeIf(p -> wSelfOpes.contains(String.valueOf(p.OperatorID)));
            if (wList.size() <= 0) {
                return;
            }
            // ⑤创建待办互检消息
            List<BFCMessage> wBFCMessageList = new ArrayList<>();
            BFCMessage wMessage;
            SimpleDateFormat wSDF = new SimpleDateFormat("yyyyMMdd");
            int wShiftID = Integer.parseInt(wSDF.format(Calendar.getInstance().getTime()));
            // ①若只有一个班长，则自己做自检、自己做互检
            for (SFCTaskStep wSFCTaskStep : wList) {
                boolean wIsSend = SFCTaskStepDAO.getInstance().JudgeMessageIsSend(wLoginUser, wSFCTaskStep.OperatorID,
                        wMutualTaskID, BPMEventModule.MutualCheck.getValue(), wErrorCode);
                if (wIsSend) {
                    continue;
                }

                wMessage = new BFCMessage();
                wMessage.Active = 0;
                wMessage.CompanyID = 0;
                wMessage.CreateTime = Calendar.getInstance();
                wMessage.EditTime = Calendar.getInstance();
                wMessage.ID = 0;
                wMessage.MessageID = wMutualTaskID;
                wMessage.Title = StringUtils.Format("互检 {0} {1}", wData.StepName, wData.PartNo);
                wMessage.MessageText = StringUtils.Format("【{0}】 {1}触发了互检任务【{2}】",
                        BPMEventModule.MutualCheck.getLable(), wLoginUser.Name, wData.StepName);
                wMessage.ModuleID = BPMEventModule.MutualCheck.getValue();
                wMessage.ResponsorID = wSFCTaskStep.OperatorID;
                wMessage.ShiftID = wShiftID;
                wMessage.StationID = wData.PartID;
                wMessage.Type = BFCMessageType.Task.getValue();
                wBFCMessageList.add(wMessage);
            }
            CoreServiceImpl.getInstance().BFC_UpdateMessageList(wLoginUser, wBFCMessageList);
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    @Override
    public ServiceResult<SFCAttemptRun> SFC_QueryDefaultAttemptRun(BMSEmployee wLoginUser, int wEventID) {
        ServiceResult<SFCAttemptRun> wResult = new ServiceResult<>();
        wResult.Result = new SFCAttemptRun();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            List<SFCAttemptRun> wList = SFCAttemptRunDAO.getInstance().SelectList(wLoginUser, -1, "", wLoginUser.ID, -1,
                    -1, -1, new ArrayList<>(Collections.singletonList(0)), null, null, wErrorCode);
            if (wList.size() > 0) {
                wResult.Result = wList.get(0);
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public synchronized ServiceResult<SFCAttemptRun> SFC_CreateAttemptRun(BMSEmployee wLoginUser,
                                                                          BPMEventModule wEventID) {
        ServiceResult<SFCAttemptRun> wResult = new ServiceResult<>();
        wResult.Result = new SFCAttemptRun();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            wResult.Result.Code = SFCAttemptRunDAO.getInstance().GetNewCode(wLoginUser, wErrorCode);
            wResult.Result.UpFlowID = wLoginUser.ID;
            wResult.Result.UpFlowName = wLoginUser.Name;
            wResult.Result.CreateTime = Calendar.getInstance();
            wResult.Result.SubmitTime = Calendar.getInstance();
            wResult.Result.ID = 0;
            wResult.Result.Status = SFCAttemptRunStatus.Default.getValue();
            wResult.Result.StatusText = "";
            wResult.Result.FlowType = wEventID.getValue();

            wResult.Result = (SFCAttemptRun) SFCAttemptRunDAO.getInstance().BPM_UpdateTask(wLoginUser, wResult.Result,
                    wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<SFCAttemptRun> SFC_SubmitAttemptRun(BMSEmployee wLoginUser, SFCAttemptRun wData) {
        ServiceResult<SFCAttemptRun> wResult = new ServiceResult<>();
        wResult.Result = new SFCAttemptRun();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            // 更新返修项列表
            if (wData.ItemList != null && wData.ItemList.size() > 0) {
                for (SFCRepairItem wSFCRepairItem : wData.ItemList) {
                    SFCRepairItemDAO.getInstance().Update(wLoginUser, wSFCRepairItem, wErrorCode);
                }
            }

            if (wData.OrderID > 0) {
                List<SFCRepairItem> wList = SFCRepairItemDAO.getInstance().SelectList(wLoginUser, -1, "", -1, -1,
                        wData.ID, wErrorCode);
                if (wList == null || wList.size() <= 0) {
                    // 获取未完成的返修项
                    List<RROItemTask> wItemTaskList = WDWServiceImpl.getInstance()
                            .RRO_QueryNotFinishItemList(wLoginUser, wData.OrderID).List(RROItemTask.class);
                    if (wItemTaskList != null && wItemTaskList.size() > 0) {
                        for (RROItemTask wRROItemTask : wItemTaskList) {
                            SFCRepairItem wSFCRepairItem = new SFCRepairItem();
                            wSFCRepairItem.Code = SFCRepairItemDAO.getInstance().GetNewCode(wLoginUser, wErrorCode);
                            wSFCRepairItem.Detail = wRROItemTask.Remark;
                            wSFCRepairItem.ID = 0;
                            wSFCRepairItem.Name = wRROItemTask.Content;
                            wSFCRepairItem.PartID = wRROItemTask.StationID;
                            wSFCRepairItem.PartName = APSConstans.GetFPCPartName(wSFCRepairItem.PartID);
                            wSFCRepairItem.Remark = "";
                            wSFCRepairItem.Result = SFCRepairItemResult.NotFinish.getValue();
                            wSFCRepairItem.TaskID = wData.ID;
                            wSFCRepairItem.ItemTaskID = wRROItemTask.ID;
                            wSFCRepairItem.TechnicianIDs = this.GetTechnicianIDs(wSFCRepairItem.PartID);
                            wSFCRepairItem.TechnicianID = this.GetTechnicianID(wSFCRepairItem.PartID);
                            wSFCRepairItem.TechnicianName = APSConstans.GetBMSEmployeeName(wSFCRepairItem.TechnicianID);

                            SFCRepairItemDAO.getInstance().Update(wLoginUser, wSFCRepairItem, wErrorCode);
                        }
                    }
                }
            }

            if (wData.Status == SFCAttemptRunStatus.NomalClose.getValue()) {
                wData.StatusText = SFCAttemptRunStatus.NomalClose.getLable();
            }

            // 处理驳回和同意
            if (wData.Status == 3) {
                List<SFCRepairItem> wList = null;
                if (wData.ItemList != null) {
                    wList = wData.ItemList.stream().filter(
                                    p -> p.TechnicianID == wLoginUser.ID && p.Result == SFCRepairItemResult.Submited.getValue())
                            .collect(Collectors.toList());
                }
                if (wList != null) {
                    for (SFCRepairItem wSFCRepairItem : wList) {
                        wSFCRepairItem.Result = SFCRepairItemResult.NotAgreen.getValue();
                        SFCRepairItemDAO.getInstance().Update(wLoginUser, wSFCRepairItem, wErrorCode);
                    }
                }
            } else if (wData.Status == 4) {
                List<SFCRepairItem> wList = null;
                if (wData.ItemList != null) {
                    wList = wData.ItemList.stream().filter(
                                    p -> p.TechnicianID == wLoginUser.ID && p.Result == SFCRepairItemResult.Submited.getValue())
                            .collect(Collectors.toList());
                }
                if (wList != null) {
                    for (SFCRepairItem wSFCRepairItem : wList) {
                        wSFCRepairItem.Result = SFCRepairItemResult.Agreen.getValue();
                        SFCRepairItemDAO.getInstance().Update(wLoginUser, wSFCRepairItem, wErrorCode);
                    }
                }
            }

            wResult.Result = (SFCAttemptRun) SFCAttemptRunDAO.getInstance().BPM_UpdateTask(wLoginUser, wData,
                    wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    /**
     * 根据工位查询所有工艺师集合
     */
    private String GetTechnicianIDs(int partID) {
        String wResult = "";
        try {
            List<BMSEmployee> wList = APSUtils.getInstance().QueryCraftsman(BaseDAO.SysAdmin, -1, partID, -1);
            if (wList != null && wList.size() > 0) {
                wResult = StringUtils.Join(",",
                        wList.stream().map(p -> p.Name).distinct().collect(Collectors.toList()));
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
        return wResult;
    }

    /**
     * 根据工位查询当前工艺师
     */
    private int GetTechnicianID(int partID) {
        int wResult = 0;
        try {
            List<BMSEmployee> wList = APSUtils.getInstance().QueryCraftsman(BaseDAO.SysAdmin, -1, partID, -1);
            wResult = wList.get(0).ID;
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<SFCAttemptRun> SFC_GetAttemptRun(BMSEmployee wLoginUser, int wID) {
        ServiceResult<SFCAttemptRun> wResult = new ServiceResult<>();
        wResult.Result = new SFCAttemptRun();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            wResult.Result = (SFCAttemptRun) SFCAttemptRunDAO.getInstance().BPM_GetTaskInfo(wLoginUser, wID, "",
                    wErrorCode);

            if (wResult.Result.Status == 2 || wResult.Result.Status == 3 || wResult.Result.Status == 4) {
                wResult.Result.ItemList.removeIf(p -> p.TechnicianID != wLoginUser.ID
                        && wResult.Result.ItemList.stream().anyMatch(q -> q.TechnicianID == wLoginUser.ID));
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<BPMTaskBase>> SFC_QueryAttemptRunEmployeeAll(BMSEmployee wLoginUser, int wTagTypes,
                                                                           Calendar wStartTime, Calendar wEndTime) {
        ServiceResult<List<BPMTaskBase>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            switch (TagTypes.getEnumType(wTagTypes)) {
                case Applicant:// 2发起
                    wResult.Result = SFCAttemptRunDAO.getInstance().BPM_GetSendTaskList(wLoginUser, wLoginUser.ID,
                            wStartTime, wEndTime, wErrorCode);
                    break;
                case Dispatcher:// 1待做
                    wResult.Result = SFCAttemptRunDAO.getInstance().BPM_GetUndoTaskList(wLoginUser, wLoginUser.ID,
                            wErrorCode);
                    break;
                case Approver:// 4已做
                    wResult.Result = SFCAttemptRunDAO.getInstance().BPM_GetDoneTaskList(wLoginUser, wLoginUser.ID,
                            wStartTime, wEndTime, wErrorCode);
                    break;
                default:
                    break;
            }

            if (wResult.Result.size() > 0) {
                wResult.Result = wResult.Result.stream().filter(p -> p.Status != 0).collect(Collectors.toList());
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<SFCAttemptRun>> SFC_QueryAttemptRunHistory(BMSEmployee wLoginUser, int wID, String wCode,
                                                                         int wUpFlowID, int wFollowerID, int wOrderID, int wCheckerID, int wPartID,
                                                                         Calendar wStartTime,
                                                                         Calendar wEndTime) {
        ServiceResult<List<SFCAttemptRun>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            wResult.Result = SFCAttemptRunDAO.getInstance().SelectList(wLoginUser, wUpFlowID, wCode, wUpFlowID,
                    wOrderID, wCheckerID, wPartID, null, wStartTime, wEndTime, wErrorCode);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Boolean> SFC_JugdeItem(BMSEmployee wLoginUser, int wOrderID, int wSFCAttemptRunID) {
        ServiceResult<Boolean> wResult = new ServiceResult<>();
        wResult.Result = true;
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            List<RROItemTask> wList = WDWServiceImpl.getInstance().RRO_QueryNotFinishItemList(wLoginUser, wOrderID)
                    .List(RROItemTask.class);
            if (wList == null || wList.size() <= 0) {
                return wResult;
            }

            SFCAttemptRun wTask = (SFCAttemptRun) SFCAttemptRunDAO.getInstance().BPM_GetTaskInfo(wLoginUser,
                    wSFCAttemptRunID, "", wErrorCode);
            if (wTask == null || wTask.ID <= 0 || wTask.ItemList == null || wTask.ItemList.size() <= 0) {
                wResult.Result = false;
                return wResult;
            }

            if (wTask.ItemList.stream().anyMatch(p -> wList.stream().anyMatch(q -> q.ID == p.ItemTaskID)
                    && p.Result != SFCRepairItemResult.Agreen.getValue())) {
                wResult.Result = false;
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public synchronized ServiceResult<Map<Integer, Integer>> SFC_JudgeAll(BMSEmployee wLoginUser, SFCAttemptRun wData) {
        ServiceResult<Map<Integer, Integer>> wResult = new ServiceResult<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        wResult.Result = new HashMap<>();
        try {
            // ①1 第一步 查询订单再试运单申请后所有返修项列表
            List<RROItemTask> wRROItemTaskList = new ArrayList<>();
            if (wData.OrderID > 0) {
                wRROItemTaskList = WDWServiceImpl.getInstance().RRO_QueryNotFinishItemList(wLoginUser, wData.OrderID)
                        .List(RROItemTask.class);
            }

            List<SFCRepairItem> wRItemList = SFCRepairItemDAO.getInstance().SelectList(wLoginUser, -1, "", -1, -1,
                    wData.ID, wErrorCode);

            // ②2 第二部 对比主单据中返修项列表 并补齐
            List<RROItemTask> wNewList = wRROItemTaskList.stream()
                    .filter(p -> wRItemList.stream().noneMatch(q -> q.ItemTaskID == p.ID)).collect(Collectors.toList());
            if (wNewList.size() > 0) {
                for (RROItemTask wRROItemTask : wNewList) {
                    SFCRepairItem wSFCRepairItem = new SFCRepairItem();
                    wSFCRepairItem.Code = SFCRepairItemDAO.getInstance().GetNewCode(wLoginUser, wErrorCode);
                    wSFCRepairItem.Detail = wRROItemTask.Remark;
                    wSFCRepairItem.ID = 0;
                    wSFCRepairItem.Name = wRROItemTask.Content;
                    wSFCRepairItem.PartID = wRROItemTask.StationID;
                    wSFCRepairItem.PartName = APSConstans.GetFPCPartName(wSFCRepairItem.PartID);
                    wSFCRepairItem.Remark = "";
                    wSFCRepairItem.Result = SFCRepairItemResult.NotFinish.getValue();
                    wSFCRepairItem.TaskID = wData.ID;
                    wSFCRepairItem.ItemTaskID = wRROItemTask.ID;
                    wSFCRepairItem.TechnicianIDs = this.GetTechnicianIDs(wSFCRepairItem.PartID);
                    wSFCRepairItem.TechnicianID = this.GetTechnicianID(wSFCRepairItem.PartID);
                    wSFCRepairItem.TechnicianName = APSConstans.GetBMSEmployeeName(wSFCRepairItem.TechnicianID);

                    wSFCRepairItem.ID = SFCRepairItemDAO.getInstance().Update(wLoginUser, wSFCRepairItem, wErrorCode);

                    wRItemList.add(wSFCRepairItem);
                }
            }
            // ③3 第三步 返修项状态变更（完成/取消）
            List<RROItemTask> wRROItemTaskList1 = wRROItemTaskList;
            List<SFCRepairItem> wFinishedList = wRItemList.stream()
                    .filter(p -> wRROItemTaskList1.stream().noneMatch(q -> q.ID == p.ItemTaskID))
                    .collect(Collectors.toList());
            for (SFCRepairItem wSFCRepairItem : wFinishedList) {
                wSFCRepairItem.Result = SFCRepairItemResult.Finished.getValue();
                SFCRepairItemDAO.getInstance().Update(wLoginUser, wSFCRepairItem, wErrorCode);
            }
            // ④4 筛选未完成返修项
            List<SFCRepairItem> wNFList = wRItemList.stream()
                    .filter(p -> p.Result != SFCRepairItemResult.Finished.getValue()
                            && p.Result != SFCRepairItemResult.Canceled.getValue())
                    .collect(Collectors.toList());
            // ⑤5 判断未完成返修项是否全部同意
            if (wData.Status == 4 || wData.Status == 3) {
                // ⑥// 5 剔除本工艺师对应的返修项（已提交的）
                wNFList.removeIf(
                        p -> p.TechnicianID == wLoginUser.ID && p.Result == SFCRepairItemResult.Submited.getValue());
                // ⑦// 6 判断未剔除的返修项是否全部同意
                if (wNFList.stream()
                        .allMatch(p -> p.Result == SFCRepairItemResult.Agreen.getValue()
                                || p.Result == SFCRepairItemResult.Finished.getValue()
                                || p.Result == SFCRepairItemResult.Canceled.getValue())) {
                    // ⑨// 8 如果全部同意 则返回 3：2 ，4:1
                    wResult.Result.put(3, 2);
                    wResult.Result.put(4, 1);
                } else {
                    // ⑧// 7 如果有非同意状态 则直接返回 3 ：2 ，4：2
                    wResult.Result.put(3, 2);
                    wResult.Result.put(4, 2);
                }
            } else if (wData.Status == 1) {
                if (wNFList.size() <= 0) {
                    wResult.Result.put(1, 1);
                } else {
                    wResult.Result.put(1, 2);
                }
            } else {
                if (wNFList.stream().allMatch(p -> p.Result == SFCRepairItemResult.Agreen.getValue())) {
                    wResult.Result.put(3, 2);
                    wResult.Result.put(4, 1);
                } else {
                    wResult.Result.put(3, 2);
                    wResult.Result.put(4, 2);
                }
            }
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Boolean> SFC_JudgeIsSendApply(BMSEmployee wLoginUser, SFCAttemptRun wSFCAttemptRun) {
        ServiceResult<Boolean> wResult = new ServiceResult<>();
        wResult.Result = false;
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            if (wSFCAttemptRun.OrderID <= 0) {
                return wResult;
            }

            List<SFCAttemptRun> wList = SFCAttemptRunDAO.getInstance().SelectList(wLoginUser, -1, "", -1,
                    wSFCAttemptRun.OrderID, -1, -1, null, null, null, wErrorCode);
            if (wList != null && wList.size() > 0 && wList.stream()
                    .anyMatch(p -> p.ID != wSFCAttemptRun.ID && p.Status != SFCAttemptRunStatus.Canceled.getValue())) {
                wResult.Result = true;
            }
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<SFCSequentialInfo>> SFC_QuerySequentialInfoNew(BMSEmployee wLoginUser, int wOrderID,
                                                                             String wUUID) {
        ServiceResult<List<SFCSequentialInfo>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            // ①收到电报√
            wResult.Result.addAll(SFCOrderFormDAO.getInstance().SelectTelegraphInfo(wLoginUser, wOrderID, wErrorCode));
            // ②进厂确认√
            wResult.Result.addAll(SFCOrderFormDAO.getInstance().SelectInPlantInfo(wLoginUser, wOrderID, wErrorCode));

            List<SFCSequentialInfo> wWorkList = new ArrayList<>();

            // ④开工打卡√
            wWorkList.addAll(SFCOrderFormDAO.getInstance().SelectClockInInfo(wLoginUser, wOrderID, wErrorCode));
            // ⑥预检√
            wWorkList.addAll(SFCOrderFormDAO.getInstance().SelectPreCheckInfo(wLoginUser, wOrderID, wErrorCode));
            // ⑦自检√
            wWorkList.addAll(SFCOrderFormDAO.getInstance().SelectSelfCheckInfo(wLoginUser, wOrderID, wErrorCode));
            // ⑧互检√
            wWorkList.addAll(SFCOrderFormDAO.getInstance().SelectMutalCheckInfo(wLoginUser, wOrderID, wErrorCode));
            // ⑨专检√
            wWorkList.addAll(SFCOrderFormDAO.getInstance().SelectSpecialCheckInfo(wLoginUser, wOrderID, wErrorCode));
            // ④终检√
            wWorkList.addAll(SFCOrderFormDAO.getInstance().SelectFinalCheckInfo(wLoginUser, wOrderID, wErrorCode));
            // ⑦出厂检√
            wWorkList.addAll(SFCOrderFormDAO.getInstance().SelectOutCheckInfo(wLoginUser, wOrderID, wErrorCode));

            // 根据工位、工序、操作类型、操作人去重
            // 多条件
            wWorkList = wWorkList.stream().collect(Collectors.collectingAndThen(
                    Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(
                            o -> o.getStationID() + ";" + o.getStepID() + ";" + o.getType() + ";" + o.getOperators()))),
                    ArrayList::new));

            // ①获取工位顺序字典
            Map<Integer, Integer> wPartOrderMap = SFCOrderFormDAO.getInstance().SelectPartOrderMap(wLoginUser, wOrderID,
                    wErrorCode);
            // ②工位顺序依次赋值
            for (SFCSequentialInfo wSFCSequentialInfo : wWorkList) {
                if (wPartOrderMap.containsKey(wSFCSequentialInfo.StationID)) {
                    wSFCSequentialInfo.PartOrder = wPartOrderMap.get(wSFCSequentialInfo.StationID);
                } else if (wSFCSequentialInfo.StationName.contains("终检")) {
                    wSFCSequentialInfo.PartOrder = 1000;
                } else if (wSFCSequentialInfo.StationName.contains("出厂普查")) {
                    wSFCSequentialInfo.PartOrder = 1001;
                }
            }
            // ③按照工位、工序、操作类型排序
            wWorkList.sort(
                    Comparator.comparing(SFCSequentialInfo::getPartOrder).thenComparing(SFCSequentialInfo::getStationID)
                            .thenComparing(SFCSequentialInfo::getStepID).thenComparing(SFCSequentialInfo::getType));
            // ④添加进结果集
            wResult.Result.addAll(wWorkList);

            // ③移车√
            wResult.Result.addAll(SFCOrderFormDAO.getInstance().SelectMoveCarInfo(wLoginUser, wOrderID, wErrorCode));
            // ⑩不合格评审√
            wResult.Result.addAll(SFCOrderFormDAO.getInstance().SelectNCRInfo(wLoginUser, wOrderID, wErrorCode));
            // ①返修√
            wResult.Result.addAll(SFCOrderFormDAO.getInstance().SelectRepairInfo(wLoginUser, wOrderID, wErrorCode));
            // ②异常√
            wResult.Result.addAll(SFCOrderFormDAO.getInstance().SelectExceptionInfo(wLoginUser, wOrderID, wErrorCode));
            // ③预检问题项√
            wResult.Result.addAll(SFCOrderFormDAO.getInstance().SelectProblemInfo(wLoginUser, wOrderID, wErrorCode));
            // ⑤竣工确认√
            wResult.Result
                    .addAll(SFCOrderFormDAO.getInstance().SelectFinishConfirmInfo(wLoginUser, wOrderID, wErrorCode));
            // ⑥出厂申请√
            wResult.Result.addAll(SFCOrderFormDAO.getInstance().SelectOutApplyInfo(wLoginUser, wOrderID, wErrorCode));
            // ⑧出厂确认√
            wResult.Result.addAll(SFCOrderFormDAO.getInstance().SelectOutConfirmInfo(wLoginUser, wOrderID, wErrorCode));

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> SFC_DeleteRepeat(BMSEmployee wLoginUser) {
        ServiceResult<Integer> wResult = new ServiceResult<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            wResult.Result = SFCTaskStepDAO.getInstance().DeleteRepeat(wLoginUser, wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<SFCBOMTask>> SFC_QueryBOMTaskEmployeeAllNew(BMSEmployee wLoginUser, Calendar wStartTime,
                                                                          Calendar wEndTime, int wOrderID,
                                                                          int wPartID, int wLevel, int wStatus) {
        ServiceResult<List<SFCBOMTask>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            List<SFCBOMTask> wSendList;
            List<SFCBOMTask> wToDoList = new ArrayList<>();
            List<SFCBOMTask> wDoneList = new ArrayList<>();

            List<BPMTaskBase> wBaseList = SFCBOMTaskDAO.getInstance().BPM_GetSendTaskList(wLoginUser, wLoginUser.ID,
                    wStartTime, wEndTime, wErrorCode);
            wSendList = CloneTool.CloneArray(wBaseList, SFCBOMTask.class);
            // 查询数据
            List<SFCBOMTask> wList = SFCBOMTaskDAO.getInstance().SFC_QueryListByMessage(wLoginUser, wStartTime,
                    wEndTime, wErrorCode);
            if (wList.size() > 0) {
                wToDoList = wList.stream().filter(p -> p.StepID > 0).collect(Collectors.toList());
                wDoneList = wList.stream().filter(p -> p.StepID <= 0).collect(Collectors.toList());
            }

            List<Integer> wIDList = new ArrayList<>();

            for (SFCBOMTask wMTCTask : wToDoList) {
                if (wIDList.contains(wMTCTask.ID))
                    continue;
                wMTCTask.TagTypes = TaskQueryType.ToHandle.getValue();
                wResult.Result.add(wMTCTask);
                wIDList.add(wMTCTask.ID);
            }

            for (SFCBOMTask wMTCTask : wDoneList) {
                if (wIDList.contains(wMTCTask.ID))
                    continue;
                wMTCTask.TagTypes = TaskQueryType.Handled.getValue();
                wResult.Result.add(wMTCTask);
                wIDList.add(wMTCTask.ID);
            }

            for (SFCBOMTask wMTCTask : wSendList) {
                if (wIDList.contains(wMTCTask.ID))
                    continue;
                wMTCTask.TagTypes = TaskQueryType.Sended.getValue();
                wResult.Result.add(wMTCTask);
                wIDList.add(wMTCTask.ID);
            }

            wResult.Result.removeIf(p -> p.Status == 0);

            // 订单
            if (wOrderID > 0) {
                wResult.Result = wResult.Result.stream().filter(p -> p.OrderID == wOrderID)
                        .collect(Collectors.toList());
            }
            // 工位
            if (wPartID > 0) {
                wResult.Result = wResult.Result.stream().filter(p -> p.PartID == wPartID).collect(Collectors.toList());
            }
            // 等级
            if (wLevel > 0) {
                wResult.Result = wResult.Result.stream().filter(p -> p.Level == wLevel).collect(Collectors.toList());
            }
            // 状态
            if (wStatus >= 0) {
                if (wStatus == 0) {
                    wResult.Result = wResult.Result.stream()
                            .filter(p -> p.Status != 20 && p.Status != 21 && p.Status != 22)
                            .collect(Collectors.toList());
                } else if (wStatus == 1) {
                    wResult.Result = wResult.Result.stream()
                            .filter(p -> p.Status == 20 || p.Status == 21 || p.Status == 22)
                            .collect(Collectors.toList());
                }
            }

            wResult.Result.sort((o1, o2) -> o2.CreateTime.compareTo(o1.CreateTime));
            wResult.Result.sort((o1, o2) -> {
                if (o1.TagTypes == 1) {
                    return -1;
                } else if (o2.TagTypes == 1) {
                    return 1;
                }
                return 0;
            });

            // 排序，已完工排在最后
            List<SFCBOMTask> wFinishedList = wResult.Result.stream().filter(p -> p.Status == 20)
                    .collect(Collectors.toList());
            wResult.Result.removeIf(p -> p.Status == 20);
            wResult.Result.addAll(wFinishedList);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<SFCBOMTask>> SFC_QueryBOMTaskList(BMSEmployee wLoginUser, int wOrderID, int wPartID,
                                                                int wLevel, int wStatus, Calendar wStartTime,
                                                                Calendar wEndTime, String wMaterialNo,
                                                                String wMaterialName,
                                                                int wIsLGL, int wIsQualityLoss, int wCovaType) {
        ServiceResult<List<SFCBOMTask>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            switch (wStatus) {
                case 1:
                    wResult.Result.addAll(SFCBOMTaskDAO.getInstance().SelectList(wLoginUser, wOrderID, wPartID, -1, -1,
                            wLevel, StringUtils.parseListArgs(SFCBOMTaskStatus.NomalClose.getValue()), null, wStartTime,
                            wEndTime, wErrorCode));
                    break;
                case 0:
                    wResult.Result.addAll(
                            SFCBOMTaskDAO.getInstance().SelectList(wLoginUser, wOrderID, wPartID, -1, -1, wLevel, null,
                                    StringUtils.parseListArgs(SFCBOMTaskStatus.NomalClose.getValue(),
                                            SFCBOMTaskStatus.Canceled.getValue(), SFCBOMTaskStatus.Default.getValue(),
                                            25,
                                            SFCBOMTaskStatus.ExceptionClose.getValue()),
                                    wStartTime, wEndTime, wErrorCode));
                    break;
                default:
                    wResult.Result.addAll(SFCBOMTaskDAO.getInstance().SelectList(wLoginUser, wOrderID, wPartID, -1, -1,
                            wLevel, null, null, wStartTime, wEndTime, wErrorCode));
                    break;
            }
            wResult.Result.sort((o1, o2) -> o2.SubmitTime.compareTo(o1.SubmitTime));

            if (wIsLGL >= 0) {
                wResult.Result = wResult.Result.stream().filter(p -> p.IsLGL == wIsLGL).collect(Collectors.toList());
            }

            if (wIsQualityLoss >= 0) {
                wResult.Result = wResult.Result.stream().filter(p -> p.IsQualityLoss == wIsQualityLoss)
                        .collect(Collectors.toList());
            }

            if (wCovaType > 0) {
                wResult.Result = wResult.Result.stream().filter(p -> p.CovaType == wCovaType)
                        .collect(Collectors.toList());
            }

            for (SFCBOMTask sfcbomTask : wResult.Result) {
                sfcbomTask.CovaTypeText = sfcbomTask.CovaType == 1 ? "是" : "否";
                sfcbomTask.IsLGLText = sfcbomTask.IsLGL == 1 ? "是" : "否";
                sfcbomTask.SAPStatusText = sfcbomTask.SAPStatus == 1 ? "推送成功"
                        : sfcbomTask.SAPStatus == 0 ? "暂未推送" : sfcbomTask.SAPStatusText;
                sfcbomTask.PostMsg = sfcbomTask.IsPost == 1 ? "过账成功"
                        : sfcbomTask.IsPost == 0 ? "--" : sfcbomTask.PostMsg;
            }

            if (wResult.Result.size() <= 0 || wStatus == 1) {
                return wResult;
            }

            // ①通过物料号或物料名称模糊搜索偶换件评审单号
            if (StringUtils.isNotEmpty(wMaterialName) || StringUtils.isNotEmpty(wMaterialNo)) {
                List<Integer> wTaskIDList = SFCBOMTaskDAO.getInstance().SelectIDListByMaterial(wLoginUser,
                        wMaterialName, wMaterialNo, wErrorCode);
                wResult.Result = wResult.Result.stream().filter(p -> wTaskIDList.stream().anyMatch(q -> q == p.ID))
                        .collect(Collectors.toList());
            }

            List<BPMTaskBase> wBaseList = SFCBOMTaskDAO.getInstance().BPM_GetUndoTaskList(wLoginUser, wLoginUser.ID,
                    wErrorCode);

            if (wBaseList == null || wBaseList.size() <= 0) {
                return wResult;
            }
            for (BPMTaskBase wTaskBase : wBaseList) {
                if (!(wTaskBase instanceof SFCBOMTask))
                    continue;
                SFCBOMTask wSFCBOMTask = (SFCBOMTask) wTaskBase;
                wSFCBOMTask.TagTypes = TaskQueryType.ToHandle.getValue();
                for (int i = 0; i < wResult.Result.size(); i++) {
                    if (wResult.Result.get(i).ID == wSFCBOMTask.ID)
                        wResult.Result.set(i, wSFCBOMTask);
                }
            }
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<SFCAttemptRun>> SFC_QueryAttemptRunEmployeeAllNew(BMSEmployee wLoginUser,
                                                                                Calendar wStartTime,
                                                                                Calendar wEndTime, int wProductID,
                                                                                String wPartNo, int wStatus) {
        ServiceResult<List<SFCAttemptRun>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            List<SFCAttemptRun> wSendList;
            List<SFCAttemptRun> wToDoList;
            List<SFCAttemptRun> wDoneList;

            List<BPMTaskBase> wBaseList = SFCAttemptRunDAO.getInstance().BPM_GetSendTaskList(wLoginUser,
                    wLoginUser.getID(), wStartTime, wEndTime, wErrorCode);
            wSendList = CloneTool.CloneArray(wBaseList, SFCAttemptRun.class);

            wBaseList = SFCAttemptRunDAO.getInstance().BPM_GetUndoTaskList(wLoginUser, wLoginUser.getID(), wErrorCode);
            wToDoList = CloneTool.CloneArray(wBaseList, SFCAttemptRun.class);

            wBaseList = SFCAttemptRunDAO.getInstance().BPM_GetDoneTaskList(wLoginUser, wLoginUser.getID(), wStartTime,
                    wEndTime, wErrorCode);
            wDoneList = CloneTool.CloneArray(wBaseList, SFCAttemptRun.class);
            List<Integer> wIDList = new ArrayList<>();
            for (SFCAttemptRun wSFCAttemptRun : wToDoList) {
                if (wIDList.contains(wSFCAttemptRun.ID))
                    continue;
                wSFCAttemptRun.TagTypes = TaskQueryType.ToHandle.getValue();
                wResult.Result.add(wSFCAttemptRun);
                wIDList.add(wSFCAttemptRun.ID);
            }

            for (SFCAttemptRun wSFCAttemptRun : wDoneList) {
                if (wIDList.contains(wSFCAttemptRun.ID))
                    continue;
                wSFCAttemptRun.TagTypes = TaskQueryType.Handled.getValue();
                wResult.Result.add(wSFCAttemptRun);
                wIDList.add(wSFCAttemptRun.ID);
            }

            for (SFCAttemptRun wSFCAttemptRun : wSendList) {
                if (wIDList.contains(wSFCAttemptRun.ID))
                    continue;
                wSFCAttemptRun.TagTypes = TaskQueryType.Sended.getValue();
                wResult.Result.add(wSFCAttemptRun);
                wIDList.add(wSFCAttemptRun.ID);
            }

            wResult.Result.removeIf(p -> p.Status == 0);

            // 车型
            if (wProductID > 0) {
                wResult.Result = wResult.Result.stream().filter(p -> p.ProductID == wProductID)
                        .collect(Collectors.toList());
            }
            // 车号
            if (StringUtils.isNotEmpty(wPartNo)) {
                wResult.Result = wResult.Result.stream().filter(p -> p.PartNo.contains(wPartNo))
                        .collect(Collectors.toList());
            }
            // 状态
            if (wStatus >= 0) {
                if (wStatus == 0) {
                    wResult.Result = wResult.Result.stream()
                            .filter(p -> p.Status != 20 && p.Status != 21 && p.Status != 22)
                            .collect(Collectors.toList());
                } else if (wStatus == 1) {
                    wResult.Result = wResult.Result.stream()
                            .filter(p -> p.Status == 20 || p.Status == 21 || p.Status == 22)
                            .collect(Collectors.toList());
                }
            }

            wResult.Result.sort((o1, o2) -> o2.CreateTime.compareTo(o1.CreateTime));
            wResult.Result.sort((o1, o2) -> {
                if (o1.TagTypes == 1) {
                    return -1;
                } else if (o2.TagTypes == 1) {
                    return 1;
                }
                return 0;
            });
            // 排序

        } catch (Exception e) {
            wResult.FaultCode += e.getMessage();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<SFCAttemptRun>> SFC_QueryAttemptRunList(BMSEmployee wLoginUser, int wOrderID, int wLineID,
                                                                      int wCustomerID, int wProductID, String wPartNo, int wStatus, Calendar wStartTime,
                                                                      Calendar wEndTime) {
        ServiceResult<List<SFCAttemptRun>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {

            switch (wStatus) {
                case 1:
                    wResult.Result.addAll(SFCAttemptRunDAO.getInstance().SelectList(wLoginUser, wOrderID, wLineID,
                            wCustomerID, wProductID, wPartNo, -1, -1,
                            StringUtils.parseListArgs(SFCAttemptRunStatus.NomalClose.getValue()), null, wStartTime,
                            wEndTime, wErrorCode));
                    break;
                case 0:
                    wResult.Result.addAll(SFCAttemptRunDAO.getInstance().SelectList(wLoginUser, wOrderID, wLineID,
                            wCustomerID, wProductID, wPartNo, -1, -1, null,
                            StringUtils.parseListArgs(SFCAttemptRunStatus.NomalClose.getValue(),
                                    SFCAttemptRunStatus.Canceled.getValue(), SFCAttemptRunStatus.Default.getValue(),
                                    SFCAttemptRunStatus.ExceptionClose.getValue()),
                            wStartTime, wEndTime, wErrorCode));

                    break;
                default:
                    wResult.Result.addAll(SFCAttemptRunDAO.getInstance().SelectList(wLoginUser, wOrderID, wLineID,
                            wCustomerID, wProductID, wPartNo, -1, -1, null, null, wStartTime, wEndTime, wErrorCode));
                    break;
            }
            wResult.Result.sort((o1, o2) -> o2.SubmitTime.compareTo(o1.SubmitTime));

            if (wResult.Result.size() <= 0 || wStatus == 1) {
                return wResult;
            }
            List<BPMTaskBase> wBaseList = SFCAttemptRunDAO.getInstance().BPM_GetUndoTaskList(wLoginUser, wLoginUser.ID,
                    wErrorCode);

            if (wBaseList == null || wBaseList.size() <= 0) {
                return wResult;
            }
            for (BPMTaskBase wTaskBase : wBaseList) {
                if (!(wTaskBase instanceof SFCAttemptRun))
                    continue;
                SFCAttemptRun wSFCAttemptRun = (SFCAttemptRun) wTaskBase;
                wSFCAttemptRun.TagTypes = TaskQueryType.ToHandle.getValue();
                for (int i = 0; i < wResult.Result.size(); i++) {
                    if (wResult.Result.get(i).ID == wSFCAttemptRun.ID)
                        wResult.Result.set(i, wSFCAttemptRun);
                }
            }

        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<FPCPart>> SFC_QueryLoginStationList(BMSEmployee wLoginUser) {
        ServiceResult<List<FPCPart>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {

            List<BMSWorkCharge> wWorkChargeList = CoreServiceImpl.getInstance().FMC_QueryWorkChargeList(wLoginUser)
                    .List(BMSWorkCharge.class);

            boolean wIsFilter = wLoginUser.DepartmentID != 0;

            // 有权限不过滤
            if (CoreServiceImpl.getInstance()
                    .BMS_CheckPowerByAuthorityID(wLoginUser.CompanyID, wLoginUser.ID, 900110, 0, 0)
                    .Info(Boolean.class)) {
                wIsFilter = false;
            }

            // 有班组配置，不过滤
            if (wLoginUser.DepartmentID > 0) {
                List<BMSClassPartRole> bmsClassPartRoles = BMSClassPartRoleDAO.getInstance().SelectList(wLoginUser, -1,
                        wLoginUser.DepartmentID, 1, wErrorCode);
                if (bmsClassPartRoles.size() > 0) {
                    wIsFilter = false;
                }
            }

            if (wIsFilter) {
                wWorkChargeList = wWorkChargeList.stream()
                        .filter(p -> p.Active == 1 && p.ClassID == wLoginUser.DepartmentID)
                        .collect(Collectors.toList());
            }

            if (wWorkChargeList.size() > 0) {
                for (BMSWorkCharge wBMSWorkCharge : wWorkChargeList) {
                    FPCPart wFPCPart = APSConstans.GetFPCPart(wBMSWorkCharge.StationID);
                    if (wFPCPart == null || wFPCPart.ID <= 0) {
                        continue;
                    }
                    if (wResult.Result.stream().noneMatch(p -> p.ID == wFPCPart.ID)) {
                        wResult.Result.add(wFPCPart);
                    }
                }
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error("SFC_QueryLoginStationList", e);
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<BMSEmployee>> SFC_QueryPartCheckerList(BMSEmployee wLoginUser, int wPartID) {
        ServiceResult<List<BMSEmployee>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            wResult.Result = APSUtils.getInstance().QueryChecker(wLoginUser, -1, wPartID, -1);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<BMSEmployee>> SFC_QueryTechnicianList(BMSEmployee wLoginUser) {
        ServiceResult<List<BMSEmployee>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            wResult.Result = APSUtils.getInstance().QueryCraftsman(wLoginUser, -1, -1, -1);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<CFGItem>> SFC_QueryModuleList(BMSEmployee wLoginUser) {
        ServiceResult<List<CFGItem>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            wResult.Result = BPMEventModule.getEnumList();

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<String> SFC_ExportBOMTaskList(BMSEmployee wLoginUser, Calendar wDate) {
        ServiceResult<String> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            List<MBSApiLogDetails> wMBSApiLogDetailsList = new ArrayList<>();

            MyExcelSheet wMyExcelSheet = GetMyExcelSheet(wLoginUser, wDate, wMBSApiLogDetailsList);

            List<MyExcelSheet> wMyExcelSheetList = new ArrayList<>(Collections.singletonList(wMyExcelSheet));

            long startTime = System.currentTimeMillis();

            wResult.Result = ExcelUtil.ExportData(wMyExcelSheetList, "偶换件物料清单");

            long endTime = System.currentTimeMillis();
            MBSApiLogDetails wMBSApiLogDetails = new MBSApiLogDetails("ExportData", (int) (endTime - startTime));
            wMBSApiLogDetailsList.add(wMBSApiLogDetails);

            int wMs = 0;
            for (MBSApiLogDetails wItem : wMBSApiLogDetailsList) {
                wMs += wItem.Times;
            }
            if (wMs > 1000) {
                int wMsClone = wMs;
                ExecutorService wES = Executors.newFixedThreadPool(1);
                wES.submit(() -> {
                    String wJson = JSON.toJSONString(wMBSApiLogDetailsList);
                    MBSApiLogAnalysis wMBSApiLogAnalysis = new MBSApiLogAnalysis(0,
                            "/MESLOCOAPS/api/SFCBOMTask/Export", wJson, wMsClone, Calendar.getInstance());
                    LFSServiceImpl.getInstance().MBS_UpdateApiLogAnalysis(wLoginUser, wMBSApiLogAnalysis);
                });
                wES.shutdown();
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    private MyExcelSheet GetMyExcelSheet(BMSEmployee wLoginUser, Calendar wDate,
                                         List<MBSApiLogDetails> wMBSApiLogDetailsList) {
        MyExcelSheet wResult = new MyExcelSheet();
        try {
            Calendar wBaseTime = Calendar.getInstance();
            wBaseTime.set(2010, 0, 1, 0, 0, 0);

            Calendar wStartTime = Calendar.getInstance();
            Calendar wEndTime = Calendar.getInstance();
            if (wDate.compareTo(wBaseTime) <= 0) {
                wStartTime.set(Calendar.HOUR_OF_DAY, 0);
                wStartTime.set(Calendar.MINUTE, 0);
                wStartTime.set(Calendar.SECOND, 0);

                wEndTime.set(Calendar.HOUR_OF_DAY, 23);
                wEndTime.set(Calendar.MINUTE, 59);
                wEndTime.set(Calendar.SECOND, 59);
            } else {
                int wYear = wDate.get(Calendar.YEAR);
                int wMonth = wDate.get(Calendar.MONTH);
                int wDay = wDate.get(Calendar.DATE);

                wStartTime.set(wYear, wMonth, wDay, 0, 0, 0);
                wEndTime.set(wYear, wMonth, wDay, 23, 59, 59);
            }

            SimpleDateFormat wSDF = new SimpleDateFormat("yyyyMMdd");
            String wShiftID = wSDF.format(wDate.getTime());

            OutResult<Integer> wErrorCode = new OutResult<>(0);

            long startTime = System.currentTimeMillis();

            List<Integer> wIDList = SFCBOMTaskDAO.getInstance().GetCompletedListByTime(wLoginUser, wShiftID,
                    wErrorCode);

            long endTime = System.currentTimeMillis();
            MBSApiLogDetails wMBSApiLogDetails = new MBSApiLogDetails("GetCompletedListByTime",
                    (int) (endTime - startTime));
            wMBSApiLogDetailsList.add(wMBSApiLogDetails);

            wResult.HeaderList = new ArrayList<>(Arrays.asList("行号", "单号", "车号", "工位", "工序", "物料编码", "物料名称", "数量",
                    "描述", "处理意见", "责任", "必换偶换", "必修偶修", "评估类型", "等级", "申请人", "工艺师备注"));
            wResult.SheetName = "偶换件物料清单";
            wResult.TitleName = "物料清单";
            wResult.DataList = new ArrayList<>();

            if (wIDList.size() <= 0) {
                return wResult;
            }

            startTime = System.currentTimeMillis();

            List<SFCBOMTask> wList = SFCBOMTaskDAO.getInstance().SelectList(wLoginUser, wIDList, null, null,
                    wErrorCode);

            endTime = System.currentTimeMillis();
            wMBSApiLogDetails = new MBSApiLogDetails("SelectList", (int) (endTime - startTime));
            wMBSApiLogDetailsList.add(wMBSApiLogDetails);

            int wIndex = 1;

            startTime = System.currentTimeMillis();

            SetBOMTaskValue(wResult, wShiftID, wList, wIndex);

            endTime = System.currentTimeMillis();
            wMBSApiLogDetails = new MBSApiLogDetails("SetBOMTaskValue", (int) (endTime - startTime));
            wMBSApiLogDetailsList.add(wMBSApiLogDetails);
        } catch (Exception e) {
            logger.error(e.toString());
        }
        return wResult;
    }

    /**
     * 获取某节点填写的属性值(字符串)
     */
    private String GetNodeValue(List<BPMActivitiHisTask> wHisList, String wNodeName) {
        String wResult = "";
        try {
            if (wHisList == null || wHisList.size() <= 0) {
                return wResult;
            }

            if (wHisList.stream().anyMatch(p -> p.ActivitiID.equals(wNodeName))) {
                BPMActivitiHisTask wHisTask = wHisList.stream().filter(p -> p.ActivitiID.equals(wNodeName)).findFirst()
                        .get();
                if (wHisTask.HisTaskVarinstList == null || wHisTask.HisTaskVarinstList.size() <= 0) {
                    return wResult;
                }

                if (wHisTask.HisTaskVarinstList.stream().anyMatch(p -> p.VariableName.equals("Remark"))) {
                    BPMActivitiHisTaskVarinst wVarinst = wHisTask.HisTaskVarinstList.stream()
                            .filter(p -> p.VariableName.equals("Remark")).findFirst().get();
                    wResult = wVarinst.Value.toString();
                }
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
        return wResult;
    }

    /**
     * 赋值操作
     */
    private void SetBOMTaskValue(MyExcelSheet wResult, String wShiftID, List<SFCBOMTask> wList, int wIndex) {
        try {
            for (SFCBOMTask wSFCBOMTask : wList) {
                // ①设置工艺师备注
                List<BPMActivitiHisTask> wHisList = BPMServiceImpl.getInstance()
                        .BPM_GetActivitiHisTaskByPIId(BaseDAO.SysAdmin, wSFCBOMTask.FlowID)
                        .List(BPMActivitiHisTask.class);
                String wARemark = "";
                String wBRemark = "";
                String wCRemark = "";
                if (wHisList != null && wHisList.size() > 0) {
                    wARemark = GetNodeValue(wHisList, "z偶换1014");
                    wBRemark = GetNodeValue(wHisList, "z偶换1008");
                    wCRemark = GetNodeValue(wHisList, "z偶换1006");
                }

                if (wSFCBOMTask.SFCBOMTaskItemList.size() <= 0) {
                    List<String> wValueList = new ArrayList<>(
                            Arrays.asList(String.valueOf(wIndex++), wSFCBOMTask.Code, wSFCBOMTask.PartNo,
                                    wSFCBOMTask.PartName, wSFCBOMTask.PartPointName, wSFCBOMTask.MaterialNo,
                                    wSFCBOMTask.MaterialName, String.valueOf(wSFCBOMTask.MaterialNumber),
                                    wSFCBOMTask.Disposal, wSFCBOMTask.ReviewCommentsName,
                                    wSFCBOMTask.ResponsibilityName, "-", "-", "-", wSFCBOMTask.LevelName, wSFCBOMTask.UpFlowName));
                    wResult.DataList.add(wValueList);

                    continue;
                }

                if (wSFCBOMTask.Status != 20) {
                    if (wSFCBOMTask.ConfirmedLevels.contains("A")) {
                        List<SFCBOMTaskItem> wTaskList = wSFCBOMTask.SFCBOMTaskItemList.stream()
                                .filter(p -> p.Level == 1 && p.Status != 2 && p.ShiftID.equals(wShiftID))
                                .collect(Collectors.toList());
                        for (SFCBOMTaskItem wSFCBOMTaskItem : wTaskList) {
                            List<String> wValueList = new ArrayList<>(Arrays.asList(String.valueOf(wIndex++),
                                    wSFCBOMTask.Code, wSFCBOMTask.PartNo, wSFCBOMTask.PartName,
                                    wSFCBOMTask.PartPointName, wSFCBOMTaskItem.MaterialNo, wSFCBOMTaskItem.MaterialName,
                                    String.valueOf(wSFCBOMTaskItem.MaterialNumber), wSFCBOMTask.Disposal,
                                    wSFCBOMTaskItem.ReviewCommentsName, wSFCBOMTaskItem.ResponsibilityName,
                                    APSReplaceType.getEnumType(wSFCBOMTaskItem.ReplaceType).getLable(),
                                    APSOutSourceType.getEnumType(wSFCBOMTaskItem.OutsourceType).getLable(),
                                    SFCBOMTaskSAPType.getEnumType(wSFCBOMTaskItem.SapType).getLable(),
                                    wSFCBOMTaskItem.LevelName, wSFCBOMTask.UpFlowName, wARemark));

                            wResult.DataList.add(wValueList);
                        }
                    }
                    if (wSFCBOMTask.ConfirmedLevels.contains("B")) {
                        List<SFCBOMTaskItem> wTaskList = wSFCBOMTask.SFCBOMTaskItemList.stream()
                                .filter(p -> p.Level == 2 && p.Status != 2 && p.ShiftID.equals(wShiftID))
                                .collect(Collectors.toList());
                        for (SFCBOMTaskItem wSFCBOMTaskItem : wTaskList) {
                            List<String> wValueList = new ArrayList<>(Arrays.asList(String.valueOf(wIndex++),
                                    wSFCBOMTask.Code, wSFCBOMTask.PartNo, wSFCBOMTask.PartName,
                                    wSFCBOMTask.PartPointName, wSFCBOMTaskItem.MaterialNo, wSFCBOMTaskItem.MaterialName,
                                    String.valueOf(wSFCBOMTaskItem.MaterialNumber), wSFCBOMTask.Disposal,
                                    wSFCBOMTaskItem.ReviewCommentsName, wSFCBOMTaskItem.ResponsibilityName,
                                    APSReplaceType.getEnumType(wSFCBOMTaskItem.ReplaceType).getLable(),
                                    APSOutSourceType.getEnumType(wSFCBOMTaskItem.OutsourceType).getLable(),
                                    SFCBOMTaskSAPType.getEnumType(wSFCBOMTaskItem.SapType).getLable(),
                                    wSFCBOMTaskItem.LevelName, wSFCBOMTask.UpFlowName, wBRemark));

                            wResult.DataList.add(wValueList);
                        }
                    }
                    if (wSFCBOMTask.ConfirmedLevels.contains("C")) {
                        List<SFCBOMTaskItem> wTaskList = wSFCBOMTask.SFCBOMTaskItemList.stream()
                                .filter(p -> p.Level == 3 && p.Status != 2 && p.ShiftID.equals(wShiftID))
                                .collect(Collectors.toList());
                        for (SFCBOMTaskItem wSFCBOMTaskItem : wTaskList) {
                            List<String> wValueList = new ArrayList<>(Arrays.asList(String.valueOf(wIndex++),
                                    wSFCBOMTask.Code, wSFCBOMTask.PartNo, wSFCBOMTask.PartName,
                                    wSFCBOMTask.PartPointName, wSFCBOMTaskItem.MaterialNo, wSFCBOMTaskItem.MaterialName,
                                    String.valueOf(wSFCBOMTaskItem.MaterialNumber), wSFCBOMTask.Disposal,
                                    wSFCBOMTaskItem.ReviewCommentsName, wSFCBOMTaskItem.ResponsibilityName,
                                    APSReplaceType.getEnumType(wSFCBOMTaskItem.ReplaceType).getLable(),
                                    APSOutSourceType.getEnumType(wSFCBOMTaskItem.OutsourceType).getLable(),
                                    SFCBOMTaskSAPType.getEnumType(wSFCBOMTaskItem.SapType).getLable(),
                                    wSFCBOMTaskItem.LevelName, wSFCBOMTask.UpFlowName, wCRemark));

                            wResult.DataList.add(wValueList);
                        }
                    }
                } else {
                    wSFCBOMTask.SFCBOMTaskItemList = wSFCBOMTask.SFCBOMTaskItemList.stream()
                            .filter(p -> p.Status != 2 && p.ShiftID.equals(wShiftID)).collect(Collectors.toList());
                    for (SFCBOMTaskItem wSFCBOMTaskItem : wSFCBOMTask.SFCBOMTaskItemList) {
                        String wRemark = "";
                        if (wSFCBOMTaskItem.Level == 1) {
                            wRemark = wARemark;
                        } else if (wSFCBOMTaskItem.Level == 2) {
                            wRemark = wBRemark;
                        } else if (wSFCBOMTaskItem.Level == 3) {
                            wRemark = wCRemark;
                        }
                        List<String> wValueList = new ArrayList<>(Arrays.asList(String.valueOf(wIndex++),
                                wSFCBOMTask.Code, wSFCBOMTask.PartNo, wSFCBOMTask.PartName, wSFCBOMTask.PartPointName,
                                wSFCBOMTaskItem.MaterialNo, wSFCBOMTaskItem.MaterialName,
                                String.valueOf(wSFCBOMTaskItem.MaterialNumber), wSFCBOMTask.Disposal,
                                wSFCBOMTaskItem.ReviewCommentsName, wSFCBOMTaskItem.ResponsibilityName,
                                APSReplaceType.getEnumType(wSFCBOMTaskItem.ReplaceType).getLable(),
                                APSOutSourceType.getEnumType(wSFCBOMTaskItem.OutsourceType).getLable(),
                                SFCBOMTaskSAPType.getEnumType(wSFCBOMTaskItem.SapType).getLable(),
                                wSFCBOMTaskItem.LevelName, wSFCBOMTask.UpFlowName, wRemark));

                        wResult.DataList.add(wValueList);
                    }
                }
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    @Override
    public ServiceResult<List<SFCSequentialInfoNew>> SFC_QuerySequentialInfoNew_V2(BMSEmployee wLoginUser,
                                                                                   int wOrderID) {
        ServiceResult<List<SFCSequentialInfoNew>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            List<SFCSequentialInfo> wList;

            SimpleDateFormat wSdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");

            // ①收到电报√
            wList = SFCOrderFormDAO.getInstance().SelectTelegraphInfo(wLoginUser, wOrderID, wErrorCode);

            int wIndex = 1;
            for (SFCSequentialInfo wSFCSequentialInfo : wList) {
                SFCSequentialInfoNew wItem = new SFCSequentialInfoNew(wIndex++, "收到电报", wSFCSequentialInfo.Operators,
                        wSdf.format(wSFCSequentialInfo.EndTime.getTime()), "/", "/", "/", "/", "/", "/");
                wResult.Result.add(wItem);
            }

            // ②进厂确认√
            wList = SFCOrderFormDAO.getInstance().SelectInPlantInfo(wLoginUser, wOrderID, wErrorCode);
            for (SFCSequentialInfo wSFCSequentialInfo : wList) {
                SFCSequentialInfoNew wItem = new SFCSequentialInfoNew(wIndex++, "机车进厂", wSFCSequentialInfo.Operators,
                        wSdf.format(wSFCSequentialInfo.EndTime.getTime()), "/", "/", "/", "/", "/", "/");
                wResult.Result.add(wItem);
            }

            List<SFCSequentialInfo> wWorkList = new ArrayList<>();

            // ④开工打卡√
            wWorkList.addAll(SFCOrderFormDAO.getInstance().SelectClockInInfo(wLoginUser, wOrderID, wErrorCode));
            // ⑥预检√
            wWorkList.addAll(SFCOrderFormDAO.getInstance().SelectPreCheckInfo(wLoginUser, wOrderID, wErrorCode));
            // ⑦自检√
            wWorkList.addAll(SFCOrderFormDAO.getInstance().SelectSelfCheckInfo(wLoginUser, wOrderID, wErrorCode));
            // ⑧互检√
            wWorkList.addAll(SFCOrderFormDAO.getInstance().SelectMutalCheckInfo(wLoginUser, wOrderID, wErrorCode));
            // ⑨专检√
            wWorkList.addAll(SFCOrderFormDAO.getInstance().SelectSpecialCheckInfo(wLoginUser, wOrderID, wErrorCode));
            // ④终检√
            wWorkList.addAll(SFCOrderFormDAO.getInstance().SelectFinalCheckInfo(wLoginUser, wOrderID, wErrorCode));
            // ⑦出厂检√
            wWorkList.addAll(SFCOrderFormDAO.getInstance().SelectOutCheckInfo(wLoginUser, wOrderID, wErrorCode));

            // 根据工位、工序
            // 多条件
            List<SFCSequentialInfo> wStepList = wWorkList.stream()
                    .collect(Collectors.collectingAndThen(
                            Collectors.toCollection(() -> new TreeSet<>(
                                    Comparator.comparing(o -> o.getStationID() + ";" + o.getStepID()))),
                            ArrayList::new));

            // ①获取工位顺序字典
            Map<Integer, Integer> wPartOrderMap = SFCOrderFormDAO.getInstance().SelectPartOrderMap(wLoginUser, wOrderID,
                    wErrorCode);
            // ②工位顺序依次赋值
            for (SFCSequentialInfo wSFCSequentialInfo : wStepList) {
                if (wPartOrderMap.containsKey(wSFCSequentialInfo.StationID)) {
                    wSFCSequentialInfo.PartOrder = wPartOrderMap.get(wSFCSequentialInfo.StationID);
                } else if (wSFCSequentialInfo.StationName.contains("终检")) {
                    wSFCSequentialInfo.PartOrder = 1000;
                } else if (wSFCSequentialInfo.StationName.contains("出厂普查")) {
                    wSFCSequentialInfo.PartOrder = 1001;
                }
            }
            // ③按照工位、工序、操作类型排序
            wStepList.sort(
                    Comparator.comparing(SFCSequentialInfo::getPartOrder).thenComparing(SFCSequentialInfo::getStationID)
                            .thenComparing(SFCSequentialInfo::getStepID).thenComparing(SFCSequentialInfo::getType));

            Calendar wBaseTime = Calendar.getInstance();
            wBaseTime.set(2000, 0, 1, 0, 0, 0);

            // 遍历赋值
            for (SFCSequentialInfo wSFCSequentialInfo : wStepList) {
                String wTypeText;
                String checkInfo = "";
                String mCheckInfo = "/";
                String sCheckInfo = "/";

                if (wSFCSequentialInfo.StationName.contains("预检")) {
                    wTypeText = "预检任务";

                    if (wWorkList.stream()
                            .anyMatch(p -> p.StationID == wSFCSequentialInfo.StationID
                                    && p.StepID == wSFCSequentialInfo.StepID
                                    && p.Type == SFCSequentialInfoType.PreCheck.getValue())) {
                        SFCSequentialInfo wInfo = wWorkList.stream()
                                .filter(p -> p.StationID == wSFCSequentialInfo.StationID
                                        && p.StepID == wSFCSequentialInfo.StepID
                                        && p.Type == SFCSequentialInfoType.PreCheck.getValue())
                                .findFirst().get();
                        checkInfo = StringUtils.Format("{0}({1})", wInfo.Operators,
                                wSdf.format(wInfo.EndTime.getTime()));
                    }

                } else if (wSFCSequentialInfo.StationName.contains("终检")) {
                    wTypeText = "终检任务";

                    if (wWorkList.stream()
                            .anyMatch(p -> p.StationID == wSFCSequentialInfo.StationID
                                    && p.StepID == wSFCSequentialInfo.StepID
                                    && p.Type == SFCSequentialInfoType.FinalCheck.getValue())) {
                        SFCSequentialInfo wInfo = wWorkList.stream()
                                .filter(p -> p.StationID == wSFCSequentialInfo.StationID
                                        && p.StepID == wSFCSequentialInfo.StepID
                                        && p.Type == SFCSequentialInfoType.FinalCheck.getValue())
                                .findFirst().get();
                        checkInfo = StringUtils.Format("{0}({1})", wInfo.Operators,
                                wSdf.format(wInfo.EndTime.getTime()));
                    }
                } else if (wSFCSequentialInfo.StationName.contains("普查")) {
                    wTypeText = "普查任务";

                    if (wWorkList.stream()
                            .anyMatch(p -> p.StationID == wSFCSequentialInfo.StationID
                                    && p.StepID == wSFCSequentialInfo.StepID
                                    && p.Type == SFCSequentialInfoType.OutCheck.getValue())) {
                        SFCSequentialInfo wInfo = wWorkList.stream()
                                .filter(p -> p.StationID == wSFCSequentialInfo.StationID
                                        && p.StepID == wSFCSequentialInfo.StepID
                                        && p.Type == SFCSequentialInfoType.OutCheck.getValue())
                                .findFirst().get();
                        checkInfo = StringUtils.Format("{0}({1})", wInfo.Operators,
                                wSdf.format(wInfo.EndTime.getTime()));
                    }
                } else {
                    wTypeText = "生产任务";

                    if (wWorkList.stream()
                            .anyMatch(p -> p.StationID == wSFCSequentialInfo.StationID
                                    && p.StepID == wSFCSequentialInfo.StepID
                                    && p.Type == SFCSequentialInfoType.SelfCheck.getValue())) {
                        SFCSequentialInfo wInfo = wWorkList.stream()
                                .filter(p -> p.StationID == wSFCSequentialInfo.StationID
                                        && p.StepID == wSFCSequentialInfo.StepID
                                        && p.Type == SFCSequentialInfoType.SelfCheck.getValue())
                                .findFirst().get();
                        checkInfo = StringUtils.Format("{0}({1})", wInfo.Operators,
                                wSdf.format(wInfo.EndTime.getTime()));
                    }

                    if (wWorkList.stream()
                            .anyMatch(p -> p.StationID == wSFCSequentialInfo.StationID
                                    && p.StepID == wSFCSequentialInfo.StepID
                                    && p.Type == SFCSequentialInfoType.MutualCheck.getValue())) {
                        SFCSequentialInfo wInfo = wWorkList.stream()
                                .filter(p -> p.StationID == wSFCSequentialInfo.StationID
                                        && p.StepID == wSFCSequentialInfo.StepID
                                        && p.Type == SFCSequentialInfoType.MutualCheck.getValue())
                                .findFirst().get();
                        mCheckInfo = StringUtils.Format("{0}({1})", wInfo.Operators,
                                wSdf.format(wInfo.EndTime.getTime()));
                    }

                    if (wWorkList.stream()
                            .anyMatch(p -> p.StationID == wSFCSequentialInfo.StationID
                                    && p.StepID == wSFCSequentialInfo.StepID
                                    && p.Type == SFCSequentialInfoType.SpecialCheck.getValue())) {
                        SFCSequentialInfo wInfo = wWorkList.stream()
                                .filter(p -> p.StationID == wSFCSequentialInfo.StationID
                                        && p.StepID == wSFCSequentialInfo.StepID
                                        && p.Type == SFCSequentialInfoType.SpecialCheck.getValue())
                                .findFirst().get();
                        sCheckInfo = StringUtils.Format("{0}({1})", wInfo.Operators,
                                wSdf.format(wInfo.EndTime.getTime()));
                    }
                }

                String clockInfo = "";
                if (wWorkList.stream()
                        .anyMatch(p -> p.StationID == wSFCSequentialInfo.StationID
                                && p.StepID == wSFCSequentialInfo.StepID
                                && p.Type == SFCSequentialInfoType.ClockIn.getValue())) {
                    SFCSequentialInfo wInfo = wWorkList.stream()
                            .filter(p -> p.StationID == wSFCSequentialInfo.StationID
                                    && p.StepID == wSFCSequentialInfo.StepID
                                    && p.Type == SFCSequentialInfoType.ClockIn.getValue())
                            .findFirst().get();
                    clockInfo = StringUtils.Format("{0}({1})", wInfo.Operators, wSdf.format(wInfo.EndTime.getTime()));
                }

                SFCSequentialInfoNew wItem = new SFCSequentialInfoNew(wIndex++, wTypeText, "/", "/",
                        wSFCSequentialInfo.StationName, wSFCSequentialInfo.StepName, clockInfo, checkInfo, mCheckInfo,
                        sCheckInfo);
                wResult.Result.add(wItem);
            }

            // ⑤竣工确认√
            wList = SFCOrderFormDAO.getInstance().SelectFinishConfirmInfo(wLoginUser, wOrderID, wErrorCode);
            for (SFCSequentialInfo wSFCSequentialInfo : wList) {
                SFCSequentialInfoNew wItem = new SFCSequentialInfoNew(wIndex++, "竣工确认", wSFCSequentialInfo.Operators,
                        wSdf.format(wSFCSequentialInfo.EndTime.getTime()), "/", "/", "/", "/", "/", "/");
                wResult.Result.add(wItem);
            }
            // ⑥出厂申请√
            wList = SFCOrderFormDAO.getInstance().SelectOutApplyInfo(wLoginUser, wOrderID, wErrorCode);
            for (SFCSequentialInfo wSFCSequentialInfo : wList) {
                SFCSequentialInfoNew wItem = new SFCSequentialInfoNew(wIndex++, "出厂申请", wSFCSequentialInfo.Operators,
                        wSdf.format(wSFCSequentialInfo.EndTime.getTime()), "/", "/", "/", "/", "/", "/");
                wResult.Result.add(wItem);
            }
            // ⑧出厂确认√
            wList = SFCOrderFormDAO.getInstance().SelectOutConfirmInfo(wLoginUser, wOrderID, wErrorCode);
            for (SFCSequentialInfo wSFCSequentialInfo : wList) {
                SFCSequentialInfoNew wItem = new SFCSequentialInfoNew(wIndex++, "机车出厂", wSFCSequentialInfo.Operators,
                        wSdf.format(wSFCSequentialInfo.EndTime.getTime()), "/", "/", "/", "/", "/", "/");
                wResult.Result.add(wItem);
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<String> SFC_IsOverEqua(BMSEmployee wLoginUser, SFCBOMTask wTask) {
        ServiceResult<String> wResult = new ServiceResult<>();
        wResult.Result = "";
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            if (wTask.CovaType == 1) {
                // 易损易耗超定额判定
                for (SFCBOMTaskItem wItem : wTask.SFCBOMTaskItemList) {
                    double wUsedNum = SFCBOMTaskDAO.getInstance().SFC_QueryUsedNum(wLoginUser, wTask, wItem,
                            wErrorCode);
                    if (wUsedNum >= wItem.Quota) {
                        MSSMaterial wMaterial = APSBOMItemDAO.getInstance().GetMaterialByID(wLoginUser,
                                wItem.MaterialID, wErrorCode);
                        wResult.Result = StringUtils.Format("提示：{1}【{0}】超定额了。定额数：{2}，已领用或已申请领用：{3}，还需领用：{4}。",
                                wMaterial.MaterialNo, wMaterial.MaterialName, wItem.Quota,
                                String.valueOf(wUsedNum).replace(".0", ""), wItem.MaterialNumber);
                        return wResult;
                    }
                }

                return wResult;
            }

            for (SFCBOMTaskItem wItem : wTask.SFCBOMTaskItemList) {
                if (wItem.BOMItemID <= 0 || StringUtils.isNotEmpty(wItem.QualityLossBig)
                        || StringUtils.isNotEmpty(wItem.QualityLossSmall)) {
                    continue;
                }

                String wMsg = APSBOMItemDAO.getInstance().IsOverEqua(wLoginUser, wTask, wItem, wErrorCode);
                if (StringUtils.isNotEmpty(wMsg)) {
                    wResult.Result = wMsg;
                    return wResult;
                }
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<SFCBOMTask> SFC_UpdateBOMTask(BMSEmployee wLoginUser, SFCBOMTask wData) {
        ServiceResult<SFCBOMTask> wResult = new ServiceResult<>();
        wResult.Result = new SFCBOMTask();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            wResult.Result = SFCBOMTaskDAO.getInstance().Update(wLoginUser, wData, wErrorCode);

            if (wData.SFCBOMTaskItemList != null && wData.SFCBOMTaskItemList.size() > 0) {
                for (SFCBOMTaskItem wSFCBOMTaskItem : wData.SFCBOMTaskItemList) {
                    wSFCBOMTaskItem.SFCBOMTaskID = wResult.Result.ID;
                    SFCBOMTaskItemDAO.getInstance().Update(wLoginUser, wSFCBOMTaskItem, wErrorCode);
                }
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> SFC_UpdateQuota(BMSEmployee wLoginUser) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            List<Integer> wItemIDList = SFCBOMTaskItemDAO.getInstance().GetQuotaZeroList(wLoginUser, wErrorCode);
            for (Integer wItemID : wItemIDList) {
                SFCBOMTaskItem wItem = SFCBOMTaskItemDAO.getInstance().SelectByID(wLoginUser, wItemID, wErrorCode);
                SFCBOMTask wTask = (SFCBOMTask) SFCBOMTaskDAO.getInstance().BPM_GetTaskInfo(wLoginUser,
                        wItem.SFCBOMTaskID, "", wErrorCode);
                if (wTask == null || wTask.ID <= 0 || wTask.PartID <= 0 || wTask.PartPointID <= 0
                        || wItem.MaterialID <= 0) {
                    continue;
                }
                double wQuota = SFCBOMTaskItemDAO.getInstance().GetQuota(wLoginUser, wTask.PartID, wTask.PartPointID,
                        wItem.MaterialID, wErrorCode);
                if (wQuota <= 0) {
                    continue;
                }
                wItem.Quota = wQuota;
                SFCBOMTaskItemDAO.getInstance().Update(wLoginUser, wItem, wErrorCode);
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<OMSOrder>> SFC_QueryOrderListByLogID(BMSEmployee wLoginUser, int wLogID) {
        ServiceResult<List<OMSOrder>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            List<TCMMaterialChangeLog> wLogList = TCMMaterialChangeLogDAO.getInstance().SelectListWithoutSub(wLoginUser,
                    wLogID, null, null, wErrorCode);
            if (wLogList == null || wLogList.size() <= 0) {
                wResult.CustomResult.put("Used", new ArrayList<OMSOrder>());
                wResult.CustomResult.put("Less", new ArrayList<OMSOrder>());
                return wResult;
            }

            if (StringUtils.isEmpty(wLogList.get(0).OrderIDList)) {
                wResult.CustomResult.put("Used", new ArrayList<OMSOrder>());
                wResult.CustomResult.put("Less", new ArrayList<OMSOrder>());
                return wResult;
            }

            List<Integer> wOrderIDList = StringUtils.parseIntList(wLogList.get(0).OrderIDList.split(","));

            List<OMSOrder> wOrderList = OMSOrderDAO.getInstance().SelectListByIDList(wLoginUser, wOrderIDList,
                    wErrorCode);
            List<Integer> wUsedIDList = SFCBOMTaskDAO.getInstance().SelectedUsedOrderIDList(wLoginUser, wLogID,
                    wErrorCode);
            List<OMSOrder> wUsedOrderList = wOrderList.stream()
                    .filter(p -> wUsedIDList.stream().anyMatch(q -> q == p.ID)).collect(Collectors.toList());
            List<OMSOrder> wLessOrderList = wOrderList.stream()
                    .filter(p -> wUsedIDList.stream().noneMatch(q -> q == p.ID))
                    .collect(Collectors.toList());
            wResult.CustomResult.put("Used", wUsedOrderList);
            wResult.CustomResult.put("Less", wLessOrderList);
            wResult.Result = wOrderList;

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> SFC_UpdateAssessType(BMSEmployee wLoginUser, List<SFCBOMTaskItem> wDataList) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            if (wDataList == null || wDataList.size() <= 0) {
                return wResult;
            }

            SimpleDateFormat wSDF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String wCurrentTime = wSDF.format(Calendar.getInstance().getTime());

            // ①修改偶换件子表的评估类型
            for (SFCBOMTaskItem wSFCBOMTaskItem : wDataList) {
                SFCBOMTaskItemDAO.getInstance().Update(wLoginUser, wSFCBOMTaskItem, wErrorCode);

                String wContent = StringUtils.Format("【{0}】在【{1}】将【{2}】的评估类型属性修改为【{3}】", wLoginUser.Name, wCurrentTime,
                        wSFCBOMTaskItem.MaterialNo + wSFCBOMTaskItem.MaterialName, wSFCBOMTaskItem.SapTypeName);

                LFSOperationLog wLFSOperationLog = new LFSOperationLog(0, wSFCBOMTaskItem.SFCBOMTaskID,
                        LFSOperationLogType.EvaluationTypeUpdate.getValue(),
                        LFSOperationLogType.EvaluationTypeUpdate.getLable(),
                        wLoginUser.ID, wLoginUser.Name, Calendar.getInstance(), wContent);
                LFSServiceImpl.getInstance().LFS_UpdateOperationLog(wLoginUser, wLFSOperationLog);
            }

            // 获取orderid
            SFCBOMTask wSFCBOMTask = (SFCBOMTask) SFCBOMTaskDAO.getInstance().BPM_GetTaskInfo(wLoginUser,
                    wDataList.get(0).SFCBOMTaskID, "", wErrorCode);
            if (wSFCBOMTask == null || wSFCBOMTask.ID <= 0) {
                wResult.FaultCode += "获取偶换件评审单失败，请联系系统管理员!";
                return wResult;
            }

            // ②根据偶换件单据ID查询台车BOM
            for (SFCBOMTaskItem wSFCBOMTaskItem : wDataList) {
                int wApsBoMID = APSBOMItemDAO.getInstance().SelectIDListByBomTaskItemID(wLoginUser,
                        wSFCBOMTaskItem.ID, wSFCBOMTask.OrderID,
                        wErrorCode);
                if (wApsBoMID <= 0) {
                    continue;
                }
                // ③找到非打了删除标记的数据，打上删除标记
                APSServiceImpl.getInstance().APS_BomItemPropertyChange(wLoginUser, wApsBoMID, "X", 0);
            }

            // ④重新推送偶换件的物料
            APSServiceImpl.getInstance().APS_BOMTaskToSAP(wLoginUser, wDataList);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<SFCTaskStepCar>> SFC_QueryDispatchCarList(BMSEmployee wLoginUser) {
        ServiceResult<List<SFCTaskStepCar>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            // ①从日计划中获取在修订单ID集合
            List<Integer> wOrderIDList = SFCTaskStepDAO.getInstance().SelectReparingOrderIDList(wLoginUser, wErrorCode);
            // ②根据订单ID集合获取订单列表
            List<OMSOrder> wOrderList = OMSOrderDAO.getInstance().SelectListByIDList(wLoginUser, wOrderIDList,
                    wErrorCode);
            // ③遍历获取数据
            for (OMSOrder wOMSOrder : wOrderList) {
                SFCTaskStepCar wTaskStepCar = SFCTaskStepDAO.getInstance().GetSFCTaskStepCar(wLoginUser, wOMSOrder,
                        wErrorCode);
                // ④添加到结果集
                wResult.Result.add(wTaskStepCar);
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<SFCTaskStepPart>> SFC_QueryDispatchPartList(BMSEmployee wLoginUser, int wOrderID) {
        ServiceResult<List<SFCTaskStepPart>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            // ①根据订单ID获取工位ID列表
            List<Integer> wPartIDList = SFCTaskStepDAO.getInstance().SelectPartIDList(wLoginUser, wOrderID, wErrorCode);
            // ①获取工位排程顺序
            // ①排序
            List<LFSWorkAreaStation> wASList = APSConstans.GetLFSWorkAreaStationList().values().stream()
                    .filter(p -> p.Active == 1).sorted(Comparator.comparing(LFSWorkAreaStation::getOrderNum))
                    .collect(Collectors.toList());
            // ①获取订单
            OMSOrder wOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wOrderID, wErrorCode);
            // ②遍历工位ID获取数据
            for (LFSWorkAreaStation wLFSWorkAreaStation : wASList) {
                if (wPartIDList.stream().noneMatch(p -> p == wLFSWorkAreaStation.StationID)) {
                    continue;
                }

                FPCPart wFPCPart = APSConstans.GetFPCPart(wLFSWorkAreaStation.StationID);
                if (wFPCPart == null || wFPCPart.ID <= 0) {
                    continue;
                }

                SFCTaskStepPart wSFCTaskStepPart = SFCTaskStepDAO.getInstance().GetSFCTaskStepPart(wLoginUser, wFPCPart,
                        wOrderID, wOrder, wErrorCode);
                // ③添加到结果集
                wResult.Result.add(wSFCTaskStepPart);
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<String> SFC_ExportBOMTaskListByOrder(BMSEmployee wLoginUser, int wOrderID) {
        ServiceResult<String> wResult = new ServiceResult<>();
        try {

            OutResult<Integer> wErrorCode = new OutResult<>(0);

            MyExcelSheet wMyExcelSheet = GetMyExcelSheet(wLoginUser, wOrderID);

            List<MyExcelSheet> wMyExcelSheetList = new ArrayList<>(Collections.singletonList(wMyExcelSheet));

            wResult.Result = ExcelUtil.ExportData(wMyExcelSheetList, "偶换件物料清单");

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    private MyExcelSheet GetMyExcelSheet(BMSEmployee wLoginUser, int wOrderID) {
        MyExcelSheet wResult = new MyExcelSheet();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            wResult.HeaderList = new ArrayList<>(Arrays.asList("行号", "单号", "车号", "工位", "工序", "物料编码", "物料名称", "数量",
                    "描述", "处理意见", "责任", "必换偶换", "必修偶修", "评估类型", "等级", "申请人", "推送状态"));
            wResult.SheetName = "偶换件物料清单";
            wResult.TitleName = "物料清单";
            wResult.DataList = new ArrayList<>();

            List<SFCBOMTask> wList = SFCBOMTaskDAO.getInstance().SelectList(wLoginUser, wOrderID, -1, -1, -1, -1, null,
                    null, null, null, wErrorCode);

            List<Integer> wIDList = wList.stream().map(p -> p.ID).distinct().collect(Collectors.toList());

            wList = SFCBOMTaskDAO.getInstance().SelectList(wLoginUser, wIDList, null, null, wErrorCode);

            int wIndex = 1;
            for (SFCBOMTask wSFCBOMTask : wList) {
                if (wSFCBOMTask.SFCBOMTaskItemList.size() <= 0) {
                    List<String> wValueList = new ArrayList<>(Arrays.asList(String.valueOf(wIndex++),
                            wSFCBOMTask.Code, wSFCBOMTask.PartNo, wSFCBOMTask.PartName, wSFCBOMTask.PartPointName,
                            wSFCBOMTask.MaterialNo, wSFCBOMTask.MaterialName,
                            String.valueOf(wSFCBOMTask.MaterialNumber), wSFCBOMTask.Disposal,
                            wSFCBOMTask.ReviewCommentsName, wSFCBOMTask.ResponsibilityName, "-", "-", "-",
                            wSFCBOMTask.LevelName,
                            wSFCBOMTask.UpFlowName, wSFCBOMTask.SAPStatusText));
                    wResult.DataList.add(wValueList);

                    continue;
                }

                for (SFCBOMTaskItem wSFCBOMTaskItem : wSFCBOMTask.SFCBOMTaskItemList) {
                    List<String> wValueList = new ArrayList<>(Arrays.asList(String.valueOf(wIndex++),
                            wSFCBOMTask.Code, wSFCBOMTask.PartNo, wSFCBOMTask.PartName, wSFCBOMTask.PartPointName,
                            wSFCBOMTaskItem.MaterialNo, wSFCBOMTaskItem.MaterialName,
                            String.valueOf(wSFCBOMTaskItem.MaterialNumber), wSFCBOMTask.Disposal,
                            wSFCBOMTaskItem.ReviewCommentsName, wSFCBOMTaskItem.ResponsibilityName,
                            APSReplaceType.getEnumType(wSFCBOMTaskItem.ReplaceType).getLable(),
                            APSOutSourceType.getEnumType(wSFCBOMTaskItem.OutsourceType).getLable(),
                            SFCBOMTaskSAPType.getEnumType(wSFCBOMTaskItem.SapType).getLable(),
                            wSFCBOMTaskItem.LevelName, wSFCBOMTask.UpFlowName, wSFCBOMTask.SAPStatusText));

                    wResult.DataList.add(wValueList);
                }
            }
        } catch (Exception e) {
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<OMSOrder>> SFC_QueryOrderList(BMSEmployee wLoginUser) {
        ServiceResult<List<OMSOrder>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            // ①获取订单ID集合
            List<Integer> wOrderIDList = SFCBOMTaskDAO.getInstance().GetOrderIDList(wLoginUser, wErrorCode);
            // ②根据订单ID集合获取订单集合
            wResult.Result = OMSOrderDAO.getInstance().SelectListByIDList(wLoginUser, wOrderIDList, wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> SFC_BOMTaskCodeReset(BMSEmployee wLoginUser) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            int wYear = Calendar.getInstance().get(Calendar.YEAR);

            for (int i = 1; i <= 12; i++) {
                int wNumber = 1;
                // 开始时间
                Calendar wSTime = Calendar.getInstance();
                wSTime.set(wYear, i - 1, 1, 0, 0, 0);
                // 结束时间
                Calendar wETime = Calendar.getInstance();
                wETime.set(wYear, i, 1, 0, 0, 0);

                // 根据开始时间和结束时间查询ID集合
                List<SFCBOMTask> wTaskList = SFCBOMTaskDAO.getInstance().SelectListByCreateTime(wLoginUser, null,
                        wSTime, wETime, wErrorCode);
                for (SFCBOMTask wSFCBOMTask : wTaskList) {

                    wSFCBOMTask.Code = StringUtils.Format("RP{0}{1}{2}", String.valueOf(wYear),
                            String.format("%02d", i), String.format("%04d", wNumber));

                    SFCBOMTaskDAO.getInstance().BPM_UpdateCode(wLoginUser, wSFCBOMTask, wErrorCode);

                    wNumber++;
                }
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> SFC_UpdateBOMTaskSubmitTime(BMSEmployee wLoginUser) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            List<SFCBOMTask> wList = SFCBOMTaskDAO.getInstance().SelectList(wLoginUser, -1, -1, -1, -1, -1, null, null,
                    null, null, wErrorCode);
            for (SFCBOMTask wSFCBOMTask : wList) {
                if (wSFCBOMTask.FlowID <= 0)
                    continue;
                List<BPMActivitiHisTask> wHisList = BPMServiceImpl.getInstance()
                        .BPM_GetActivitiHisTaskByPIId(wLoginUser, wSFCBOMTask.FlowID).List(BPMActivitiHisTask.class);
                if (wHisList == null || wHisList.size() <= 0) {
                    continue;
                }
                Calendar wEndTime = wHisList.stream().max(Comparator.comparing(BPMActivitiHisTask::getEndTime))
                        .get().EndTime;
                SFCBOMTaskDAO.getInstance().UpdateSubmitTime(wLoginUser, wSFCBOMTask, wEndTime, wErrorCode);
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> SFC_OutsourcingProcess(BMSEmployee wLoginUser, int wSFCBomTaskID, String wItemIDs) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            // ①查询偶换件评审单
            SFCBOMTask wSFCBOMTask = (SFCBOMTask) SFCBOMTaskDAO.getInstance().BPM_GetTaskInfo(wLoginUser, wSFCBomTaskID,
                    "", wErrorCode);
            if (wSFCBOMTask == null || wSFCBOMTask.ID <= 0) {
                return wResult;
            }
            // ②查询偶换件评审单明细
            List<SFCBOMTaskItem> wItemList = SFCBOMTaskItemDAO.getInstance().SelectList(wLoginUser, -1, wSFCBomTaskID,
                    wErrorCode);
            logger.info("wItemList:" + wItemList.size());
            // ⑥根据SourceID和sourcetype查询台车BOM
            for (SFCBOMTaskItem wSFCBOMTaskItem : wItemList) {
                logger.info("wBOMItemID:" + wSFCBOMTaskItem.BOMItemID);
                if (wSFCBOMTaskItem.BOMItemID <= 0) {
                    continue;
                }

                int wAPSBomItemID = APSBOMItemDAO.getInstance().SelectIDBySource(wLoginUser, wSFCBOMTaskItem.ID,
                        wErrorCode);
                logger.info("wAPSBomItemID:" + wAPSBomItemID);
                if (wAPSBomItemID <= 0) {
                    continue;
                }

                // ⑦调用接口删除台车BOM
                APSServiceImpl.getInstance().APS_BomItemPropertyChange(wLoginUser, wAPSBomItemID, "X", 0);
                // ④将子表outsourcetype改为2
                wSFCBOMTaskItem.OutsourceType = 2;
                SFCBOMTaskItemDAO.getInstance().Update(wLoginUser, wSFCBOMTaskItem, wErrorCode);
                // ⑤遍历子表，修改对应标准BOM子项的outsourcetype为2
                MSSBOMItemDAO.getInstance().UpdateOutsourceType(wLoginUser, wSFCBOMTaskItem.BOMItemID, wErrorCode);
            }

            // ⑩调用手动推送接口，推送偶换件
            List<Integer> wItemIDList = new ArrayList<>();
            if (StringUtils.isNotEmpty(wItemIDs)) {
                String[] wIDs = wItemIDs.split(",");
                for (String wStr : wIDs) {
                    int wID = StringUtils.parseInt(wStr);
                    if (wID > 0) {
                        wItemIDList.add(wID);
                    }
                }
            }
            APSServiceImpl.getInstance().APS_BOMTaskToSAP(wLoginUser, wSFCBomTaskID, wItemIDList, -1);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> SFC_TaskStepSubmitAllNew_v3(BMSEmployee wLoginUser,
                                                              List<APSTaskStep> wAPSTaskStepList) {
        ServiceResult<Integer> wResult = new ServiceResult<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            if (wAPSTaskStepList == null || wAPSTaskStepList.size() <= 0) {
                return wResult;
            }

            if (wAPSTaskStepList.stream().anyMatch(p -> !(p.OperatorList != null && p.OperatorList.size() > 0))) {
                wResult.FaultCode = wResult.FaultCode + "提示：派工人员不能为空!";
                return wResult;
            }

            if (wAPSTaskStepList.stream().anyMatch(p -> p.Status != APSTaskStatus.Issued.getValue())) {
                wResult.FaultCode = wResult.FaultCode + "提示：请选择状态为“下达”的数据!";
                return wResult;
            }

            // 去除重复的派工人员
            wAPSTaskStepList
                    .forEach(p -> p.OperatorList = p.OperatorList.stream().distinct().collect(Collectors.toList()));

            int wShiftID = MESServer.MES_QueryShiftID(wLoginUser.CompanyID, Calendar.getInstance(), APSShiftPeriod.Day,
                    FMCShiftLevel.Day, 0);

            Calendar wBaseTime = Calendar.getInstance();
            wBaseTime.set(2000, 0, 1);

            int wNewID;
            List<BFCMessage> wMessageList = new ArrayList<>();

            List<SFCTaskStep> wSFCTaskStepList = new ArrayList<>();

            for (APSTaskStep wAPSTaskStep : wAPSTaskStepList) {
                for (int wOperatorID : wAPSTaskStep.OperatorList) {

                    SFCTaskStep wSFCTaskStep = new SFCTaskStep();
                    wSFCTaskStep.TaskStepID = wAPSTaskStep.ID;
                    wSFCTaskStep.CreateTime = Calendar.getInstance();
                    wSFCTaskStep.EndTime = wBaseTime;
                    wSFCTaskStep.ShiftID = wShiftID;
                    wSFCTaskStep.WorkHour = 0.0D;
                    wSFCTaskStep.OperatorID = wOperatorID;
                    wSFCTaskStep.ReadyTime = Calendar.getInstance();
                    wSFCTaskStep.MonitorID = wLoginUser.ID;
                    wSFCTaskStep.Type = (wAPSTaskStep.TaskPartID > 0) ? SFCTaskStepType.Step.getValue()
                            : SFCTaskStepType.Quality.getValue();
                    wNewID = (SFC_UpdateTaskStep(wLoginUser, wSFCTaskStep)).Result;
                    wSFCTaskStep.ID = wNewID;
                    if (wNewID > 0) {
                        wSFCTaskStepList.add(wSFCTaskStep);
                    }

                    this.CreateMessage(wLoginUser, wShiftID, wSFCTaskStep, wNewID, wMessageList, wAPSTaskStep,
                            wOperatorID);
                }

                wAPSTaskStep.IsDispatched = true;

                // 赋值检验员
                List<BMSEmployee> wUerList = APSUtils.getInstance().QueryChecker(wLoginUser, -1,
                        wAPSTaskStep.PartID, wLoginUser.DepartmentID);
                if (wUerList != null && wUerList.size() > 0) {
                    wAPSTaskStep.MaterialNo = StringUtils.Join(",",
                            wUerList.stream().map(p -> p.ID).collect(Collectors.toList()));
                }

                APSTaskStepDAO.getInstance().Update(wLoginUser, wAPSTaskStep, wErrorCode);
            }

            ExecutorService wES = Executors.newFixedThreadPool(1);
            wES.submit(() -> {
                // 更新默认人员
                for (APSTaskStep wAPSTaskStep : wAPSTaskStepList) {
                    if (wSFCTaskStepList.stream().anyMatch(p -> p.TaskStepID == wAPSTaskStep.ID)) {
                        SFCTaskStep wItem = wSFCTaskStepList.stream().filter(p -> p.TaskStepID == wAPSTaskStep.ID)
                                .findFirst().get();
                        UpdateDefaultPerson(wLoginUser, wErrorCode, wItem.ID, wAPSTaskStep);
                    }
                }

                // 发送消息
                CoreServiceImpl.getInstance().BFC_UpdateMessageList(wLoginUser, wMessageList);

                // 判断工序任务中是否存在抱轴箱组装工序计划
                String wPlanStepIDs = MESSystemConfigDAO.getInstance().SelectValueByKey(BaseDAO.SysAdmin,
                        "central.control.plan.stepids", wErrorCode);
                if (StringUtils.isNotEmpty(wPlanStepIDs)) {
                    List<Integer> wPlanStepIDList = StringUtils.parseIntList(wPlanStepIDs.split(","));
                    if (wPlanStepIDList.size() > 0) {
                        // 判断工序任务中是否存在抱轴箱组装工序计划
                        if (wAPSTaskStepList.stream().anyMatch(p -> wPlanStepIDList.contains(p.StepID))) {
                            // 推送抱轴箱组装工序计划
                            MyHelperServiceImpl.getInstance().APS_AutoSendPlanToCentralControl();
                        }
                    }
                }
            });
            wES.shutdown();
        } catch (Exception e) {
            wResult.FaultCode = wResult.FaultCode + e;
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<String> SFC_ExportBOMTaskListByTimeSlot(BMSEmployee wLoginUser, Calendar wStartTime,
                                                                 Calendar wEndTime) {
        ServiceResult<String> wResult = new ServiceResult<>();
        wResult.Result = "";
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            List<SFCBOMTaskExcel> wList = SFCBOMTaskDAO.getInstance().SFC_QueryBOMTaskExcelList(wLoginUser, wStartTime,
                    wEndTime, wErrorCode);

            MyExcelSheet wMyExcelSheet = SFCBOMTaskDAO.getInstance().GetMyExcelSheet(wList);

            List<MyExcelSheet> wMyExcelSheetList = new ArrayList<>(Collections.singletonList(wMyExcelSheet));

            wResult.Result = ExcelUtil.ExportData(wMyExcelSheetList, "偶换件清单");

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<SFCBatchBOMItem> SFC_QueryBatchBOMItem(BMSEmployee wLoginUser, int wID) {
        ServiceResult<SFCBatchBOMItem> wResult = new ServiceResult<>();
        wResult.Result = new SFCBatchBOMItem();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            wResult.Result = SFCBatchBOMItemDAO.getInstance().SelectByID(wLoginUser, wID, wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<SFCBatchBOMItem>> SFC_QueryBatchBOMItemList(BMSEmployee wLoginUser, int wProductID,
                                                                          int wLineID, int wPartID, int wPartPointID,
                                                                          int wReplaceType, int wOutSourceType,
                                                                          int wActive, String wMaterial,
                                                                          Calendar wStartTime, Calendar wEndTime) {
        ServiceResult<List<SFCBatchBOMItem>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            wResult.Result = SFCBatchBOMItemDAO.getInstance().SelectList(wLoginUser, -1, wProductID, wLineID,
                    wPartID, wPartPointID, wReplaceType, wOutSourceType, -1, wActive, wMaterial, wStartTime, wEndTime,
                    wErrorCode);

            // 查询线边库存
            if (wResult.Result.size() > 0) {
                List<Integer> wMaterialIDList = wResult.Result.stream().map(p -> p.MaterialID).distinct()
                        .collect(Collectors.toList());
                Map<Integer, Double> wLineStockMap = SFCBatchBOMItemDAO.getInstance().SFC_QueryLineStockMap(wLoginUser,
                        wMaterialIDList, wErrorCode);
                for (SFCBatchBOMItem wSFCBatchBOMItem : wResult.Result) {
                    if (wLineStockMap.containsKey(wSFCBatchBOMItem.MaterialID)) {
                        wSFCBatchBOMItem.LineStock = wLineStockMap.get(wSFCBatchBOMItem.MaterialID);
                    }
                }
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> SFC_UpdateBatchBOMItem(BMSEmployee wLoginUser, SFCBatchBOMItem wSFCBatchBOMItem) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            if (wSFCBatchBOMItem.ID == 0) {
                List<SFCBatchBOMItem> wSFCBatchBOMItemList = SFCBatchBOMItemDAO.getInstance().SelectList(wLoginUser, -1,
                        wSFCBatchBOMItem.ProductID, wSFCBatchBOMItem.LineID, wSFCBatchBOMItem.PartID,
                        wSFCBatchBOMItem.PartPointID, wSFCBatchBOMItem.ReplaceType, wSFCBatchBOMItem.OutSourceType,
                        -1, 1, wSFCBatchBOMItem.MaterialNo, null, null,
                        wErrorCode);
                if (wSFCBatchBOMItemList.size() > 0) {
                    wResult.FaultCode += "该数据已存在，不可重复添加!";
                    return wResult;
                }
            }

            wResult.Result = SFCBatchBOMItemDAO.getInstance().Update(wLoginUser, wSFCBatchBOMItem, wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> SFC_ActiveBatchBOMItemList(BMSEmployee wLoginUser, List<SFCBatchBOMItem> wList,
                                                             int wActive) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            for (SFCBatchBOMItem wSFCBatchBOMItem : wList) {
                wSFCBatchBOMItem.Active = wActive;
                SFCBatchBOMItemDAO.getInstance().Update(wLoginUser, wSFCBatchBOMItem, wErrorCode);
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> SFC_UpdateBatchBOMItemRate(BMSEmployee wLoginUser, SFCBatchBOMItem wSFCBatchBOMItem) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            wResult.Result = SFCBatchBOMItemDAO.getInstance().Update(wLoginUser, wSFCBatchBOMItem, wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> SFC_UpdateBatchBOMItemMinFQTY(BMSEmployee wLoginUser,
                                                                SFCBatchBOMItem wSFCBatchBOMItem) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            wResult.Result = SFCBatchBOMItemDAO.getInstance().Update(wLoginUser, wSFCBatchBOMItem, wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<MSSBOMItem>> SFC_QueryEvenBOMItemList(BMSEmployee wLoginUser, int wProductID,
                                                                    int wLineID, int wPartID, int wPartPointID,
                                                                    String wMaterial) {
        ServiceResult<List<MSSBOMItem>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            List<Integer> wMaterialIDList = new ArrayList<>();
            if (StringUtils.isNotEmpty(wMaterial)) {
                wMaterialIDList = SFCBatchBOMItemDAO.getInstance().QueryMaterialID(wLoginUser, wMaterial, wErrorCode);
                if (wMaterialIDList.size() <= 0) {
                    return wResult;
                }
            }

            List<MSSBOM> wMSSBOMList = MSSBOMItemDAO.getInstance().SelectMaxBOMList(wLoginUser, wProductID, wLineID,
                    wErrorCode);
            if (wMSSBOMList == null || wMSSBOMList.size() <= 0) {
                return wResult;
            }

            List<Integer> wBOMIDList = wMSSBOMList.stream().map(p -> p.ID).collect(Collectors.toList());
            // 条件查询偶换件集合
            wResult.Result = MSSBOMItemDAO.getInstance().SelectEvenBOMItemList(wLoginUser,
                    wBOMIDList, wPartID, wPartPointID, wMaterialIDList, wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<SFCBatchBOMTaskBPM> SFC_QueryDefaultBatchBOMTaskBPM(BMSEmployee wLoginUser, int wEventID) {
        ServiceResult<SFCBatchBOMTaskBPM> wResult = new ServiceResult<>();
        wResult.Result = new SFCBatchBOMTaskBPM();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            List<SFCBatchBOMTaskBPM> wList = SFCBatchBOMTaskBPMDAO.getInstance().SelectList(wLoginUser, -1, "",
                    wLoginUser.ID,
                    0, -1, null, null, wErrorCode);
            if (wList.size() > 0) {
                wResult.Result = wList.get(0);
                wResult.Result.CreateTime = Calendar.getInstance();
                wResult.Result.UpFlowID = wLoginUser.ID;
                wResult.Result.UpFlowName = wLoginUser.Name;
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public synchronized ServiceResult<SFCBatchBOMTaskBPM> SFC_CreateBatchBOMTaskBPM(BMSEmployee wLoginUser,
                                                                                    BPMEventModule wEventID) {
        ServiceResult<SFCBatchBOMTaskBPM> wResult = new ServiceResult<>();
        wResult.Result = new SFCBatchBOMTaskBPM();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            wResult.Result.Code = SFCBatchBOMTaskBPMDAO.getInstance().GetNewCode(wLoginUser, wErrorCode);
            wResult.Result.UpFlowID = wLoginUser.ID;
            wResult.Result.UpFlowName = wLoginUser.Name;
            wResult.Result.CreateTime = Calendar.getInstance();
            wResult.Result.SubmitTime = Calendar.getInstance();
            wResult.Result.ID = 0;
            wResult.Result.Status = SFCBatchBOMTaskBPMStatus.Default.getValue();
            wResult.Result.StatusText = "";
            wResult.Result.FlowType = wEventID.getValue();

            wResult.Result = (SFCBatchBOMTaskBPM) SFCBatchBOMTaskBPMDAO.getInstance().BPM_UpdateTask(wLoginUser,
                    wResult.Result, wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<SFCBatchBOMTaskBPM> SFC_SubmitBatchBOMTaskBPM(BMSEmployee wLoginUser,
                                                                       SFCBatchBOMTaskBPM wData) {
        ServiceResult<SFCBatchBOMTaskBPM> wResult = new ServiceResult<>();
        wResult.Result = new SFCBatchBOMTaskBPM();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            if (wData.Status == 2) {
                List<SFCBatchBOMTaskBPMItem> sfcBatchBOMTaskBPMItems = SFCBatchBOMTaskBPMItemDAO.getInstance()
                        .SelectList(wLoginUser, -1, wData.ID, -1, -1, -1, -1, "",
                                wErrorCode);
                SFCBatchBOMTaskBPMItemDAO.getInstance().DeleteList(wLoginUser, sfcBatchBOMTaskBPMItems, wErrorCode);
                wData.SFCBatchBOMTaskBPMItemList.forEach(p -> p.ID = 0);
            }
            if (wData.Status == 20) {
                wData.StatusText = "已完成";
                // 创建批量偶换件配送单，并推送给WMS
                this.CreateBatchPickDemand(wLoginUser, wData);
            }

            wResult.Result = (SFCBatchBOMTaskBPM) SFCBatchBOMTaskBPMDAO.getInstance().BPM_UpdateTask(wLoginUser, wData,
                    wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    /**
     * 创建批量偶换件配送单，推送给WMS
     */
    private void CreateBatchPickDemand(BMSEmployee wLoginUser, SFCBatchBOMTaskBPM wData) {
        try {
            List<Integer> wMaterialIDList = wData.SFCBatchBOMTaskBPMItemList.stream().map(p -> p.MaterialID).distinct()
                    .collect(Collectors.toList());
            Map<Integer, Double> wMaterialMap = new HashMap<>();
            for (Integer wMaterialID : wMaterialIDList) {
                List<SFCBatchBOMTaskBPMItem> wItemList = wData.SFCBatchBOMTaskBPMItemList.stream()
                        .filter(p -> p.MaterialID == wMaterialID).collect(Collectors.toList());
                double wFQTY = 0;
                for (SFCBatchBOMTaskBPMItem wSFCBatchBOMTaskBPMItem : wItemList) {
                    wFQTY += wSFCBatchBOMTaskBPMItem.MaterialNumber;
                }
                wMaterialMap.put(wMaterialID, wFQTY);
            }
            // 创建配送单
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            String wCode = WMSBatchPickDemandDAO.getInstance().GetNewCode(wLoginUser, wErrorCode);
            WMSBatchPickDemand wWMSBatchPickDemand = new WMSBatchPickDemand(0, "1900",
                    String.valueOf(WMSOrderType.LineOrder.getValue()), wCode, Calendar.getInstance(),
                    Calendar.getInstance(), wData.ProductID, wData.LineID, WMSPickDemandStatus.Saved.getValue(),
                    wLoginUser.ID,
                    Calendar.getInstance());
            wWMSBatchPickDemand.SourceType = WMSPickDemandSourceType.BatchOHJ.getValue();
            wWMSBatchPickDemand.SourceID = wData.ID;
            wWMSBatchPickDemand.SourceCode = wData.Code;
            int wNewID = WMSBatchPickDemandDAO.getInstance().Update(wLoginUser, wWMSBatchPickDemand, wErrorCode);
            // 创建配送单明细
            if (wNewID > 0) {
                int wRowNo = 1;
                for (Integer wMaterialID : wMaterialMap.keySet()) {
                    SFCBatchBOMTaskBPMItem wSFCBatchBOMTaskBPMItem = wData.SFCBatchBOMTaskBPMItemList.stream()
                            .filter(p -> p.MaterialID == wMaterialID).findFirst().get();
                    double wFQTY = wMaterialMap.get(wMaterialID);
                    WMSBatchPickDemandItem wWMSBatchPickDemandItem = new WMSBatchPickDemandItem(0, wNewID,
                            wSFCBatchBOMTaskBPMItem.MaterialID, wSFCBatchBOMTaskBPMItem.MaterialNo,
                            wSFCBatchBOMTaskBPMItem.MaterialName, wFQTY, String.valueOf(wRowNo), "",
                            "常规新件", "", 1,
                            wSFCBatchBOMTaskBPMItem.UnitText);
                    wWMSBatchPickDemandItem.BOMNumber = wSFCBatchBOMTaskBPMItem.FQTY;
                    WMSBatchPickDemandItemDAO.getInstance().Update(wLoginUser, wWMSBatchPickDemandItem, wErrorCode);
                    wRowNo++;
                }
                // 推送给wms
                WMSServiceImpl.getInstance().WMS_ManualPushatchPickDemand(wLoginUser, wNewID);
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    @Override
    public ServiceResult<SFCBatchBOMTaskBPM> SFC_GetBatchBOMTaskBPM(BMSEmployee wLoginUser, int wID) {
        ServiceResult<SFCBatchBOMTaskBPM> wResult = new ServiceResult<>();
        wResult.Result = new SFCBatchBOMTaskBPM();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            wResult.Result = (SFCBatchBOMTaskBPM) SFCBatchBOMTaskBPMDAO.getInstance().BPM_GetTaskInfo(wLoginUser, wID,
                    "",
                    wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<BPMTaskBase>> SFC_QueryBatchBOMTaskBPMEmployeeAll(BMSEmployee wLoginUser, int wTagTypes,
                                                                                Calendar wStartTime,
                                                                                Calendar wEndTime) {
        ServiceResult<List<BPMTaskBase>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            switch (TagTypes.getEnumType(wTagTypes)) {
                case Applicant:// 2发起
                    wResult.Result = SFCBatchBOMTaskBPMDAO.getInstance().BPM_GetSendTaskList(wLoginUser, wLoginUser.ID,
                            wStartTime, wEndTime, wErrorCode);
                    break;
                case Dispatcher:// 1待做
                    wResult.Result = SFCBatchBOMTaskBPMDAO.getInstance().BPM_GetUndoTaskList(wLoginUser, wLoginUser.ID,
                            wErrorCode);
                    break;
                case Approver:// 4已做
                    wResult.Result = SFCBatchBOMTaskBPMDAO.getInstance().BPM_GetDoneTaskList(wLoginUser, wLoginUser.ID,
                            wStartTime, wEndTime, wErrorCode);
                    break;
                default:
                    break;
            }

            if (wResult.Result.size() > 0) {
                wResult.Result = wResult.Result.stream().filter(p -> p.Status != 0).collect(Collectors.toList());
            }

            // 排序
            wResult.Result.sort(Comparator.comparing(BPMTaskBase::getCreateTime, Comparator.reverseOrder()));

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<SFCBatchBOMTaskBPM>> SFC_QueryBatchBOMTaskBPMHistory(BMSEmployee wLoginUser,
                                                                                   String wCode, int wUpFlowID,
                                                                                   int wStatus,
                                                                                   Calendar wStartTime,
                                                                                   Calendar wEndTime) {
        ServiceResult<List<SFCBatchBOMTaskBPM>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            wResult.Result = SFCBatchBOMTaskBPMDAO.getInstance().SelectList(wLoginUser, -1, wCode, wUpFlowID, wStatus,
                    -1, wStartTime, wEndTime, wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<SFCBatchBOMTaskBPM>> SFC_QueryBatchBOMTaskEmployeeAllWeb(BMSEmployee wLoginUser,
                                                                                       int wPartID, int wPartPointID,
                                                                                       String wMaterial, int wStatus,
                                                                                       Calendar wStartTime,
                                                                                       Calendar wEndTime) {
        ServiceResult<List<SFCBatchBOMTaskBPM>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            switch (wStatus) {
                case 1:
                    wResult.Result.addAll(SFCBatchBOMTaskBPMDAO.getInstance().SelectList(wLoginUser, null,
                            new ArrayList<>(Collections.singletonList(20)), null, wStartTime, wEndTime, wErrorCode));
                    break;
                case 0:
                    wResult.Result.addAll(
                            SFCBatchBOMTaskBPMDAO.getInstance().SelectList(wLoginUser, null,
                                    null, new ArrayList<>(Arrays.asList(20, 21, 22)), null, null, wErrorCode));
                    break;
                default:
                    wResult.Result.addAll(SFCBatchBOMTaskBPMDAO.getInstance().SelectList(wLoginUser, null,
                            null, null, wStartTime, wEndTime, wErrorCode));
                    break;
            }
            wResult.Result.sort((o1, o2) -> o2.SubmitTime.compareTo(o1.SubmitTime));

            // ①通过物料号或物料名称模糊搜索偶换件评审单号
            if (wPartID > 0 || wPartPointID > 0 || StringUtils.isNotEmpty(wMaterial)) {
                List<Integer> wTIDList = wResult.Result.stream().map(p -> p.ID).collect(Collectors.toList());
                if (wTIDList.size() > 0) {
                    List<Integer> wTaskIDList = SFCBatchBOMTaskBPMItemDAO.getInstance().SelectTaskIDList(wLoginUser,
                            wPartID, wPartPointID, wMaterial, wTIDList, wErrorCode);
                    wResult.Result = wResult.Result.stream().filter(p -> wTaskIDList.stream().anyMatch(q -> q == p.ID))
                            .collect(Collectors.toList());
                }
            }

            if (wResult.Result.size() <= 0 || wStatus == 1) {
                return wResult;
            }

            List<BPMTaskBase> wBaseList = SFCBatchBOMTaskBPMDAO.getInstance().BPM_GetUndoTaskList(wLoginUser,
                    wLoginUser.ID,
                    wErrorCode);

            if (wBaseList == null || wBaseList.size() <= 0) {
                return wResult;
            }
            for (BPMTaskBase wTaskBase : wBaseList) {
                if (!(wTaskBase instanceof SFCBatchBOMTaskBPM))
                    continue;
                SFCBatchBOMTaskBPM wSFCBatchBOMTaskBPM = (SFCBatchBOMTaskBPM) wTaskBase;
                wSFCBatchBOMTaskBPM.TagTypes = TaskQueryType.ToHandle.getValue();
                for (int i = 0; i < wResult.Result.size(); i++) {
                    if (wResult.Result.get(i).ID == wSFCBatchBOMTaskBPM.ID)
                        wResult.Result.set(i, wSFCBatchBOMTaskBPM);
                }
            }
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<FPCPart>> SFC_QueryBatchBOMTaskPartList(BMSEmployee wLoginUser, int wProductID,
                                                                      int wLineID) {
        ServiceResult<List<FPCPart>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            List<Integer> wPartIDList = SFCBatchBOMTaskBPMDAO.getInstance().SFC_QueryBatchBOMTaskPartList(wLoginUser,
                    wProductID, wLineID, wErrorCode);
            wResult.Result = APSConstans.GetFPCPartList().values().stream()
                    .filter(p -> wPartIDList.stream().anyMatch(q -> q == p.ID)).collect(Collectors.toList());
            wResult.Result.sort(Comparator.comparing(FPCPart::getCode));

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<FPCPartPoint>> SFC_QueryBatchBOMTaskPartPointList(BMSEmployee wLoginUser,
                                                                                int wProductID, int wLineID,
                                                                                int wPartID) {
        ServiceResult<List<FPCPartPoint>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            List<Integer> wPartPointIDList = SFCBatchBOMTaskBPMDAO.getInstance().SFC_QueryBatchBOMTaskPartPointList(
                    wLoginUser,
                    wProductID, wLineID, wPartID, wErrorCode);
            wResult.Result = APSConstans.GetFPCPartPointList().values().stream()
                    .filter(p -> wPartPointIDList.stream().anyMatch(q -> q == p.ID)).collect(Collectors.toList());
            wResult.Result.sort(Comparator.comparing(FPCPartPoint::getCode));

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<SFCBatchBOMTaskBPM>> SFC_QueryBatchBOMTaskEmployeeAllNew(BMSEmployee wLoginUser,
                                                                                       Calendar wStartTime,
                                                                                       Calendar wEndTime,
                                                                                       int wStatus) {
        ServiceResult<List<SFCBatchBOMTaskBPM>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            List<SFCBatchBOMTaskBPM> wSendList;
            List<SFCBatchBOMTaskBPM> wToDoList = new ArrayList<>();
            List<SFCBatchBOMTaskBPM> wDoneList = new ArrayList<>();

            List<BPMTaskBase> wBaseList = SFCBatchBOMTaskBPMDAO.getInstance().BPM_GetSendTaskList(wLoginUser,
                    wLoginUser.ID,
                    wStartTime, wEndTime, wErrorCode);
            wSendList = CloneTool.CloneArray(wBaseList, SFCBatchBOMTaskBPM.class);
            // 查询数据
            List<SFCBatchBOMTaskBPM> wList = SFCBatchBOMTaskBPMDAO.getInstance().SFC_QueryListByMessage(wLoginUser,
                    wStartTime,
                    wEndTime, wErrorCode);
            if (wList.size() > 0) {
                wToDoList = wList.stream().filter(p -> p.StepID > 0).collect(Collectors.toList());
                wDoneList = wList.stream().filter(p -> p.StepID <= 0).collect(Collectors.toList());
            }

            List<Integer> wIDList = new ArrayList<>();

            for (SFCBatchBOMTaskBPM wMTCTask : wToDoList) {
                if (wIDList.contains(wMTCTask.ID))
                    continue;
                wMTCTask.TagTypes = TaskQueryType.ToHandle.getValue();
                wResult.Result.add(wMTCTask);
                wIDList.add(wMTCTask.ID);
            }

            for (SFCBatchBOMTaskBPM wMTCTask : wDoneList) {
                if (wIDList.contains(wMTCTask.ID))
                    continue;
                wMTCTask.TagTypes = TaskQueryType.Handled.getValue();
                wResult.Result.add(wMTCTask);
                wIDList.add(wMTCTask.ID);
            }

            for (SFCBatchBOMTaskBPM wMTCTask : wSendList) {
                if (wIDList.contains(wMTCTask.ID))
                    continue;
                wMTCTask.TagTypes = TaskQueryType.Sended.getValue();
                wResult.Result.add(wMTCTask);
                wIDList.add(wMTCTask.ID);
            }

            wResult.Result.removeIf(p -> p.Status == 0);

            // 状态
            if (wStatus >= 0) {
                if (wStatus == 0) {
                    wResult.Result = wResult.Result.stream()
                            .filter(p -> p.Status != 20 && p.Status != 21 && p.Status != 22)
                            .collect(Collectors.toList());
                } else if (wStatus == 1) {
                    wResult.Result = wResult.Result.stream()
                            .filter(p -> p.Status == 20 || p.Status == 21 || p.Status == 22)
                            .collect(Collectors.toList());
                }
            }

            wResult.Result.sort((o1, o2) -> o2.CreateTime.compareTo(o1.CreateTime));
            wResult.Result.sort((o1, o2) -> {
                if (o1.TagTypes == 1) {
                    return -1;
                } else if (o2.TagTypes == 1) {
                    return 1;
                }
                return 0;
            });

            // 排序，已完工排在最后
            List<SFCBatchBOMTaskBPM> wFinishedList = wResult.Result.stream().filter(p -> p.Status == 20)
                    .collect(Collectors.toList());
            wResult.Result.removeIf(p -> p.Status == 20);
            wResult.Result.addAll(wFinishedList);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public String SFC_JudgeIsRepeatSend(BMSEmployee wLoginUser, SFCBOMTask wTask) {
        String wResult = "";
        try {
            OutResult<Integer> wErrorCode = new OutResult<Integer>(0);

            OMSOrder omsOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wTask.OrderID, wErrorCode);
            if (omsOrder.Status >= 5 && !(wTask.StatusText.contains("作业人员") && wTask.StatusText.contains("确认"))) {
                wResult = "已完工车辆不允许领料!";
                return wResult;
            }

            if (wTask.CovaType != 1)
                return wResult;
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<SFCOutMaterialConfig>> SFC_QueryOutMaterialConfigList(BMSEmployee wLoginUser, int wID,
                                                                                    int wProductID, int wLineID,
                                                                                    int wSuplierID, int wIsPartCode,
                                                                                    int wActive, String wMaterial,
                                                                                    int wPartID, int wOrderID) {
        ServiceResult<List<SFCOutMaterialConfig>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            List<Integer> wMaterialIDList = new ArrayList<>();
            if (StringUtils.isNotEmpty(wMaterial)) {
                wMaterialIDList = SFCBatchBOMItemDAO.getInstance().QueryMaterialID(wLoginUser, wMaterial, wErrorCode);
                if (wMaterialIDList.size() <= 0) {
                    return wResult;
                }
            }

            wResult.Result = SFCOutMaterialConfigDAO.getInstance().SelectList(wLoginUser, wID, wProductID, wLineID,
                    wSuplierID, wIsPartCode, wActive, wPartID, wMaterialIDList, wErrorCode);

            if (wResult.Result.size() > 0) {
                List<Integer> wIDList = wResult.Result.stream().map(p -> p.ID).distinct().collect(Collectors.toList());
                List<SFCOutMaterialConfigItem> wItemList = SFCOutMaterialConfigItemDAO.getInstance()
                        .SelectList(wLoginUser, wIDList, wErrorCode);
                for (SFCOutMaterialConfig wSFCOutMaterialConfig : wResult.Result) {
                    List<String> wList = new ArrayList<>();
                    List<SFCOutMaterialConfigItem> wSFCOutMaterialConfigItemList = wItemList.stream()
                            .filter(p -> p.ConfigID == wSFCOutMaterialConfig.ID).collect(Collectors.toList());
                    for (SFCOutMaterialConfigItem wSFCOutMaterialConfigItem : wSFCOutMaterialConfigItemList) {
                        wList.add(wSFCOutMaterialConfigItem.SupplierName + "-" + wSFCOutMaterialConfigItem.DeviceModel);
                    }
                    wSFCOutMaterialConfig.Suppliers = StringUtils.Join("\r\n", wList);
                }
                // 是否有当前标准，赋值
                List<Integer> wHasStandardConfigIDList = SFCOutMaterialConfigDAO.getInstance()
                        .SelectHasStandardConfigIDList(wLoginUser, wIDList,
                                wErrorCode);
                for (SFCOutMaterialConfig wSFCOutMaterialConfig : wResult.Result) {
                    if (wHasStandardConfigIDList.stream().anyMatch(p -> p == wSFCOutMaterialConfig.ID)) {
                        wSFCOutMaterialConfig.IsCurrentStandard = 1;
                    } else {
                        wSFCOutMaterialConfig.IsCurrentStandard = 0;
                    }
                }
            }

            // 委外拆修物料ID赋值
            if (wOrderID > 0 && wPartID > 0) {
                List<Integer> wIDList = wResult.Result.stream().map(p -> p.ID).distinct().collect(Collectors.toList());
                Map<Integer, Integer> wIDMap = SFCOutMaterialConfigDAO.getInstance().GetIDMap(wLoginUser, wIDList,
                        wPartID, wOrderID, wErrorCode);
                for (SFCOutMaterialConfig wSFCOutMaterialConfig : wResult.Result) {
                    if (wIDMap.containsKey(wSFCOutMaterialConfig.ID)) {
                        wSFCOutMaterialConfig.IPTOutSourceMaterialID = wIDMap.get(wSFCOutMaterialConfig.ID);
                    }
                }
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> SFC_UpdateOutMaterialConfig(BMSEmployee wLoginUser,
                                                              SFCOutMaterialConfig wSFCOutMaterialConfig) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            boolean wFlag = SFCOutMaterialConfigDAO.getInstance().IsRepeat(wLoginUser, wSFCOutMaterialConfig,
                    wErrorCode);
            if (wFlag) {
                wResult.FaultCode += "数据重复!";
                return wResult;
            }

            if (wSFCOutMaterialConfig.ID <= 0) {
                wSFCOutMaterialConfig.CreateID = wLoginUser.ID;
                wSFCOutMaterialConfig.CreateTime = Calendar.getInstance();
            }
            wSFCOutMaterialConfig.EditID = wLoginUser.ID;
            wSFCOutMaterialConfig.EditTime = Calendar.getInstance();
            wResult.Result = SFCOutMaterialConfigDAO.getInstance().Update(wLoginUser, wSFCOutMaterialConfig,
                    wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> SFC_ActiveOutMaterialConfigList(BMSEmployee wLoginUser,
                                                                  List<SFCOutMaterialConfig> wList, int wActive) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            for (SFCOutMaterialConfig wSFCOutMaterialConfig : wList) {
                wSFCOutMaterialConfig.Active = wActive;
                wSFCOutMaterialConfig.EditID = wLoginUser.ID;
                wSFCOutMaterialConfig.EditTime = Calendar.getInstance();
                SFCOutMaterialConfigDAO.getInstance().Update(wLoginUser, wSFCOutMaterialConfig, wErrorCode);
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<MSSBOMItem>> SFC_QueryOutBOMItemList(BMSEmployee wLoginUser, int wProductID,
                                                                   int wLineID, int wPartID, int wPartPointID,
                                                                   String wMaterial) {
        ServiceResult<List<MSSBOMItem>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            List<Integer> wMaterialIDList = new ArrayList<>();
            if (StringUtils.isNotEmpty(wMaterial)) {
                wMaterialIDList = SFCBatchBOMItemDAO.getInstance().QueryMaterialID(wLoginUser, wMaterial, wErrorCode);
                if (wMaterialIDList.size() <= 0) {
                    return wResult;
                }
            }

            List<MSSBOM> wMSSBOMList = MSSBOMItemDAO.getInstance().SelectMaxBOMList(wLoginUser, wProductID, wLineID,
                    wErrorCode);
            if (wMSSBOMList == null || wMSSBOMList.size() <= 0) {
                return wResult;
            }

            List<Integer> wBOMIDList = wMSSBOMList.stream().map(p -> p.ID).collect(Collectors.toList());
            // 条件查询偶换件集合
            wResult.Result = MSSBOMItemDAO.getInstance().SelectOutBOMItemList(wLoginUser,
                    wBOMIDList, wPartID, wPartPointID, wMaterialIDList, wErrorCode);
            wResult.Result.forEach(p -> p.PartName = APSConstans.GetFPCPartName(p.PlaceID));

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> SFC_UpdateOutMaterialConfigList(BMSEmployee wLoginUser,
                                                                  List<SFCOutMaterialConfig> wSFCOutMaterialConfigList) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            for (SFCOutMaterialConfig wSFCOutMaterialConfig : wSFCOutMaterialConfigList) {
                boolean wFlag = SFCOutMaterialConfigDAO.getInstance().IsRepeat(wLoginUser, wSFCOutMaterialConfig,
                        wErrorCode);
                if (wFlag) {
                    wResult.FaultCode += "数据重复!";
                    return wResult;
                }
            }

            for (SFCOutMaterialConfig wSFCOutMaterialConfig : wSFCOutMaterialConfigList) {
                if (wSFCOutMaterialConfig.ID <= 0) {
                    wSFCOutMaterialConfig.CreateID = wLoginUser.ID;
                    wSFCOutMaterialConfig.CreateTime = Calendar.getInstance();
                }
                wSFCOutMaterialConfig.EditID = wLoginUser.ID;
                wSFCOutMaterialConfig.EditTime = Calendar.getInstance();
                wResult.Result = SFCOutMaterialConfigDAO.getInstance().Update(wLoginUser, wSFCOutMaterialConfig,
                        wErrorCode);
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> SFc_UpdateOutMaterialConfigItem(BMSEmployee wLoginUser,
                                                                  SFCOutMaterialConfigItem wSFCOutMaterialConfigItem) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            wResult.Result = SFCOutMaterialConfigItemDAO.getInstance().Update(wLoginUser, wSFCOutMaterialConfigItem,
                    wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<SFCOutMaterialConfigItem>> SFC_QueryOutMaterialConfigItemList(BMSEmployee wLoginUser,
                                                                                            int wConfigID) {
        ServiceResult<List<SFCOutMaterialConfigItem>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            wResult.Result = SFCOutMaterialConfigItemDAO.getInstance().SelectList(wLoginUser, -1, wConfigID,
                    wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> SFC_DeleteOutMaterialConfigItemList(BMSEmployee wLoginUser,
                                                                      List<SFCOutMaterialConfigItem> wSFCOutMaterialConfigItemList) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            wResult = SFCOutMaterialConfigItemDAO.getInstance().DeleteList(wLoginUser, wSFCOutMaterialConfigItemList,
                    wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<String> SFC_ExportBatchBOMTaskItemAll(BMSEmployee wLoginUser, String wTaskIDs) {
        ServiceResult<String> wResult = new ServiceResult<>();
        try {
            if (StringUtils.isEmpty(wTaskIDs))
                return wResult;

            MyExcelSheet wMyExcelSheet = SFCBatchBOMItemDAO.getInstance().GetMyExcelSheet(wTaskIDs);

            List<MyExcelSheet> wMyExcelSheetList = new ArrayList<>(Collections.singletonList(wMyExcelSheet));

            wResult.Result = ExcelUtil.ExportData(wMyExcelSheetList, "易损易耗物料领用清单");
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<SFCQualityLossBPM> SFC_QueryDefaultQualityLossBPM(BMSEmployee wLoginUser, int wEventID) {
        ServiceResult<SFCQualityLossBPM> wResult = new ServiceResult<>();
        wResult.Result = new SFCQualityLossBPM();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            List<SFCQualityLossBPM> wList = SFCQualityLossBPMDAO.getInstance().SelectList(wLoginUser, -1, "",
                    wLoginUser.ID, -1, -1, -1, -1, null, null, new ArrayList<>(Collections.singletonList(0)), null,
                    null, wErrorCode);
            if (wList.size() > 0) {
                wResult.Result = wList.get(0);
                wResult.Result.CreateTime = Calendar.getInstance();
                wResult.Result.SubmitTime = Calendar.getInstance();
                wResult.Result.UpFlowName = wLoginUser.Name;
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public synchronized ServiceResult<SFCQualityLossBPM> SFC_CreateQualityLossBPM(BMSEmployee wLoginUser,
                                                                                  BPMEventModule wEventID) {
        ServiceResult<SFCQualityLossBPM> wResult = new ServiceResult<>();
        wResult.Result = new SFCQualityLossBPM();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            wResult.Result.Code = SFCQualityLossBPMDAO.getInstance().GetNewCode(wLoginUser, wErrorCode);
            wResult.Result.UpFlowID = wLoginUser.ID;
            wResult.Result.UpFlowName = wLoginUser.Name;
            wResult.Result.CreateTime = Calendar.getInstance();
            wResult.Result.SubmitTime = Calendar.getInstance();
            wResult.Result.ID = 0;
            wResult.Result.Status = SFCBOMTaskStatus.Default.getValue();
            wResult.Result.StatusText = "";
            wResult.Result.SAPStatusText = "暂未推送";
            wResult.Result.FlowType = wEventID.getValue();

            wResult.Result = (SFCQualityLossBPM) SFCQualityLossBPMDAO.getInstance().BPM_UpdateTask(wLoginUser,
                    wResult.Result, wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<SFCQualityLossBPM> SFC_SubmitQualityLossBPM(BMSEmployee wLoginUser, SFCQualityLossBPM wData) {
        ServiceResult<SFCQualityLossBPM> wResult = new ServiceResult<>();
        wResult.Result = new SFCQualityLossBPM();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            if (wData.Status == 1) {
                for (SFCQualityLossBPMItem wSFCQualityLossBPMItem : wData.SFCQualityLossBPMItemList) {
                    if (wSFCQualityLossBPMItem.OutsourceType == 1) {
                        wSFCQualityLossBPMItem.SapType = 2;
                    } else {
                        wSFCQualityLossBPMItem.SapType = 1;
                    }
                    if (wSFCQualityLossBPMItem.ReplaceType == 0 && wSFCQualityLossBPMItem.OutsourceType == 0) {
                        wSFCQualityLossBPMItem.ReplaceType = 2;
                    }
                }
                if (wData.SFCQualityLossBPMItemList.stream().anyMatch(p -> p.MaterialNumber > p.Quota)) {
                    wData.IsOverQuato = 1;
                }
            }

            if (wData.Status == 20) {
                wData.StatusText = "已完成";
                // 推送给erp和wms
                List<SFCQualityLossBPMItem> wItemList = wData.SFCQualityLossBPMItemList.stream()
                        .filter(p -> p.Status != 2).collect(Collectors.toList());
                SynchronizedToSap(wLoginUser, wData, wErrorCode, wItemList);
                // 发送待阅通知给物流采购部计划员、质量体系管理专员
                SendMessageToPurchasePlanner(wLoginUser, wData, wErrorCode);
            }

            wResult.Result = (SFCQualityLossBPM) SFCQualityLossBPMDAO.getInstance().BPM_UpdateTask(wLoginUser, wData,
                    wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    /**
     * 质量损失流程结束，发送待阅通知给物流采购部计划员
     */
    private void SendMessageToPurchasePlanner(BMSEmployee wLoginUser, SFCQualityLossBPM wData,
                                              OutResult<Integer> wErrorCode) {
        try {
            List<BMSRoleItem> wBMSRoleItemList = CoreServiceImpl.getInstance().BMS_UserAllByRoleID(wLoginUser, 43)
                    .List(BMSRoleItem.class);
            // 添加质量体系管理专员
            List<BMSRoleItem> wList = CoreServiceImpl.getInstance().BMS_UserAllByRoleID(wLoginUser, 44)
                    .List(BMSRoleItem.class);
            if (wList != null && wList.size() > 0) {
                wBMSRoleItemList.addAll(wList);
                wBMSRoleItemList = new ArrayList<BMSRoleItem>(wBMSRoleItemList.stream()
                        .collect(Collectors.toMap(BMSRoleItem::getFunctionID, account -> account, (k1, k2) -> k2))
                        .values());
            }
            List<BFCMessage> wBFCMessageList = new ArrayList<>();
            BFCMessage wMessage = null;
            int wShiftID = MESServer.MES_QueryShiftID(wLoginUser.CompanyID, Calendar.getInstance(),
                    APSShiftPeriod.Day, FMCShiftLevel.Day, 0);
            for (BMSRoleItem wItem : wBMSRoleItemList) {
                // 发送任务消息到人员
                wMessage = new BFCMessage();
                wMessage.Active = 0;
                wMessage.CompanyID = 0;
                wMessage.CreateTime = Calendar.getInstance();
                wMessage.EditTime = Calendar.getInstance();
                wMessage.ID = 0;
                wMessage.MessageID = wData.ID;
                wMessage.Title = wData.Code;
                wMessage.MessageText = StringUtils.Format("【{0}】 {1}已完成该流程的审批，请及时审阅。",
                        BPMEventModule.SFCQualityLoss.getLable(), wLoginUser.Name);
                wMessage.ModuleID = BPMEventModule.SFCQualityLoss.getValue();
                wMessage.ResponsorID = wItem.FunctionID;
                wMessage.ShiftID = wShiftID;
                wMessage.StationID = 0;
                wMessage.Type = BFCMessageType.Notify.getValue();
                wBFCMessageList.add(wMessage);
            }
            CoreServiceImpl.getInstance().BFC_UpdateMessageList(wLoginUser, wBFCMessageList);
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    @Override
    public ServiceResult<SFCQualityLossBPM> SFC_GetQualityLossBPM(BMSEmployee wLoginUser, int wID) {
        ServiceResult<SFCQualityLossBPM> wResult = new ServiceResult<>();
        wResult.Result = new SFCQualityLossBPM();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            wResult.Result = (SFCQualityLossBPM) SFCQualityLossBPMDAO.getInstance().BPM_GetTaskInfo(wLoginUser, wID, "",
                    wErrorCode);
            if (wResult.Result.OrderID > 0) {
                wResult.Result.OMSOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wResult.Result.OrderID,
                        wErrorCode);
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<BPMTaskBase>> SFC_QueryQualityLossBPMEmployeeAll(BMSEmployee wLoginUser, int wTagTypes,
                                                                               Calendar wStartTime, Calendar wEndTime) {
        ServiceResult<List<BPMTaskBase>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            switch (TagTypes.getEnumType(wTagTypes)) {
                case Applicant:// 2发起
                    wResult.Result = SFCQualityLossBPMDAO.getInstance().BPM_GetSendTaskList(wLoginUser, wLoginUser.ID,
                            wStartTime, wEndTime, wErrorCode);
                    break;
                case Dispatcher:// 1待做
                    wResult.Result = SFCQualityLossBPMDAO.getInstance().BPM_GetUndoTaskList(wLoginUser, wLoginUser.ID,
                            wErrorCode);
                    break;
                case Approver:// 4已做
                    wResult.Result = SFCQualityLossBPMDAO.getInstance().BPM_GetDoneTaskList(wLoginUser, wLoginUser.ID,
                            wStartTime, wEndTime, wErrorCode);
                    break;
                default:
                    break;
            }

            if (wResult.Result.size() > 0) {
                wResult.Result = wResult.Result.stream().filter(p -> p.Status != 0).collect(Collectors.toList());
            }

            // 排序
            wResult.Result.sort(Comparator.comparing(BPMTaskBase::getCreateTime, Comparator.reverseOrder()));

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<SFCQualityLossBPM>> SFC_QueryQualityLossBPMHistory(BMSEmployee wLoginUser, int wID,
                                                                                 String wCode, int wUpFlowID,
                                                                                 int wOrderID, int wPartID,
                                                                                 int wPartPointID,
                                                                                 int wSAPStatus, Calendar wStartTime,
                                                                                 Calendar wEndTime) {
        ServiceResult<List<SFCQualityLossBPM>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            wResult.Result = SFCQualityLossBPMDAO.getInstance().SelectList(wLoginUser, wID, wCode, wUpFlowID, wOrderID,
                    wPartID, wPartPointID, wSAPStatus, wStartTime, wEndTime, null, null, null, wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<SFCQualityLossBPM>> SFC_QueryQualityLossBPMListEmployeeAllWeb(BMSEmployee wLoginUser,
                                                                                            int wOrderID, int wPartID, int wStatus,
                                                                                            Calendar wStartTime,
                                                                                            Calendar wEndTime,
                                                                                            String wMaterial,
                                                                                            String wCode,
                                                                                            int wSAPStatus) {
        ServiceResult<List<SFCQualityLossBPM>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            switch (wStatus) {
                case 1:
                    wResult.Result.addAll(SFCQualityLossBPMDAO.getInstance().SelectList(wLoginUser, -1, wCode, -1,
                            wOrderID, wPartID, -1, wSAPStatus, wStartTime, wEndTime,
                            new ArrayList<>(Collections.singletonList(20)),
                            null, null, wErrorCode));
                    break;
                case 0:
                    wResult.Result.addAll(SFCQualityLossBPMDAO.getInstance().SelectList(wLoginUser, -1, wCode, -1,
                            wOrderID, wPartID, -1, wSAPStatus, null, null, null,
                            new ArrayList<>(Arrays.asList(0, 20, 21, 22)), null, wErrorCode));
                    break;
                default:
                    wResult.Result.addAll(SFCQualityLossBPMDAO.getInstance().SelectList(wLoginUser, -1, wCode, -1,
                            wOrderID, wPartID, -1, wSAPStatus, null, null, null,
                            new ArrayList<>(Arrays.asList(0, 20, 21, 22)), null, wErrorCode));
                    wResult.Result.addAll(SFCQualityLossBPMDAO.getInstance().SelectList(wLoginUser, -1, wCode, -1,
                            wOrderID, wPartID, -1, wSAPStatus, wStartTime, wEndTime,
                            new ArrayList<>(Arrays.asList(20, 21, 22)),
                            null, null, wErrorCode));
                    break;
            }
            wResult.Result.sort((o1, o2) -> o2.SubmitTime.compareTo(o1.SubmitTime));

            if (wResult.Result.size() <= 0 || wStatus == 1) {
                return wResult;
            }

            // ①通过物料号或物料名称模糊搜索偶换件评审单号
            if (StringUtils.isNotEmpty(wMaterial)) {
                List<Integer> wTaskIDList = SFCQualityLossBPMItemDAO.getInstance().SelectTaskIDListByMaterial(
                        wLoginUser,
                        wMaterial, wErrorCode);
                wResult.Result = wResult.Result.stream().filter(p -> wTaskIDList.stream().anyMatch(q -> q == p.ID))
                        .collect(Collectors.toList());
            }

            List<BPMTaskBase> wBaseList = SFCQualityLossBPMDAO.getInstance().BPM_GetUndoTaskList(wLoginUser,
                    wLoginUser.ID,
                    wErrorCode);

            if (wBaseList == null || wBaseList.size() <= 0) {
                return wResult;
            }
            for (BPMTaskBase wTaskBase : wBaseList) {
                if (!(wTaskBase instanceof SFCQualityLossBPM))
                    continue;
                SFCQualityLossBPM wSFCQualityLossBPM = (SFCQualityLossBPM) wTaskBase;
                wSFCQualityLossBPM.TagTypes = TaskQueryType.ToHandle.getValue();
                for (int i = 0; i < wResult.Result.size(); i++) {
                    if (wResult.Result.get(i).ID == wSFCQualityLossBPM.ID)
                        wResult.Result.set(i, wSFCQualityLossBPM);
                }
            }
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<SFCQualityLossBPM>> SFC_QuerySFCQualityLossBPMEmployeeAllNew(BMSEmployee wLoginUser,
                                                                                           Calendar wStartTime,
                                                                                           Calendar wEndTime,
                                                                                           int wOrderID, int wPartID,
                                                                                           int wStatus) {
        ServiceResult<List<SFCQualityLossBPM>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            List<SFCQualityLossBPM> wSendList;
            List<SFCQualityLossBPM> wToDoList;
            List<SFCQualityLossBPM> wDoneList;

            List<BPMTaskBase> wBaseList = SFCQualityLossBPMDAO.getInstance().BPM_GetSendTaskList(wLoginUser,
                    wLoginUser.getID(), wStartTime, wEndTime, wErrorCode);
            wSendList = CloneTool.CloneArray(wBaseList, SFCQualityLossBPM.class);

            wBaseList = SFCQualityLossBPMDAO.getInstance().BPM_GetUndoTaskList(wLoginUser, wLoginUser.getID(),
                    wErrorCode);
            wToDoList = CloneTool.CloneArray(wBaseList, SFCQualityLossBPM.class);

            wBaseList = SFCQualityLossBPMDAO.getInstance().BPM_GetDoneTaskList(wLoginUser, wLoginUser.getID(),
                    wStartTime,
                    wEndTime, wErrorCode);
            wDoneList = CloneTool.CloneArray(wBaseList, SFCQualityLossBPM.class);
            List<Integer> wIDList = new ArrayList<>();
            for (SFCQualityLossBPM wSFCQualityLossBPM : wToDoList) {
                if (wIDList.contains(wSFCQualityLossBPM.ID))
                    continue;
                wSFCQualityLossBPM.TagTypes = TaskQueryType.ToHandle.getValue();
                wResult.Result.add(wSFCQualityLossBPM);
                wIDList.add(wSFCQualityLossBPM.ID);
            }

            for (SFCQualityLossBPM wSFCQualityLossBPM : wDoneList) {
                if (wIDList.contains(wSFCQualityLossBPM.ID))
                    continue;
                wSFCQualityLossBPM.TagTypes = TaskQueryType.Handled.getValue();
                wResult.Result.add(wSFCQualityLossBPM);
                wIDList.add(wSFCQualityLossBPM.ID);
            }

            for (SFCQualityLossBPM wSFCQualityLossBPM : wSendList) {
                if (wIDList.contains(wSFCQualityLossBPM.ID))
                    continue;
                wSFCQualityLossBPM.TagTypes = TaskQueryType.Sended.getValue();
                wResult.Result.add(wSFCQualityLossBPM);
                wIDList.add(wSFCQualityLossBPM.ID);
            }

            wResult.Result.removeIf(p -> p.Status == 0);

            // 状态
            if (wStatus >= 0) {
                if (wStatus == 0) {
                    wResult.Result = wResult.Result.stream()
                            .filter(p -> p.Status != 20 && p.Status != 21 && p.Status != 22)
                            .collect(Collectors.toList());
                } else if (wStatus == 1) {
                    wResult.Result = wResult.Result.stream()
                            .filter(p -> p.Status == 20 || p.Status == 21 || p.Status == 22)
                            .collect(Collectors.toList());
                }
            }

            if (wOrderID > 0) {
                wResult.Result = wResult.Result.stream().filter(p -> p.OrderID == wOrderID)
                        .collect(Collectors.toList());
            }
            if (wPartID > 0) {
                wResult.Result = wResult.Result.stream().filter(p -> p.PartID == wPartID).collect(Collectors.toList());
            }

            wResult.Result.sort((o1, o2) -> o2.CreateTime.compareTo(o1.CreateTime));
            wResult.Result.sort((o1, o2) -> {
                if (o1.TagTypes == 1) {
                    return -1;
                } else if (o2.TagTypes == 1) {
                    return 1;
                }
                return 0;
            });
        } catch (Exception e) {
            wResult.FaultCode += e.getMessage();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> SFC_UpdateQualityLossBPM(BMSEmployee wLoginUser,
                                                           SFCQualityLossBPM wSFCQualityLossBPM) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            wResult.Result = SFCQualityLossBPMDAO.getInstance().BPM_UpdateTask(wLoginUser, wSFCQualityLossBPM,
                    wErrorCode).ID;

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> SFC_ReSendQualityLoss(BMSEmployee wLoginUser, int wSFCQualityLossID) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            SFCQualityLossBPM wSFCQualityLossBPM = (SFCQualityLossBPM) SFCQualityLossBPMDAO.getInstance()
                    .BPM_GetTaskInfo(wLoginUser,
                            wSFCQualityLossID, "", wErrorCode);
            // 推送给erp和wms
            List<SFCQualityLossBPMItem> wItemList = wSFCQualityLossBPM.SFCQualityLossBPMItemList.stream()
                    .filter(p -> p.Status != 2).collect(Collectors.toList());
            SynchronizedToSap(wLoginUser, wSFCQualityLossBPM, wErrorCode, wItemList);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> SFC_RePosting(BMSEmployee wLoginUser, int wSFCBomTaskID) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            SFCBOMTask wSFCBOMTask = (SFCBOMTask) SFCBOMTaskDAO.getInstance().BPM_GetTaskInfo(wLoginUser,
                    wSFCBomTaskID, "",
                    wErrorCode);
            wSFCBOMTask.SFCBOMTaskItemList.removeIf(p -> p.Status == 2);

            List<ZIF_MM_GET_WMS281_WSStub.ZFMM_GET_WMS281Response> wGZList = new ArrayList<>();
            for (SFCBOMTaskItem wSFCBOMTaskItem : wSFCBOMTask.SFCBOMTaskItemList) {
                List<APSBOMItem> wList = APSBOMItemDAO.getInstance().APS_QueryBOMItemList(wLoginUser,
                        wSFCBOMTask.OrderID,
                        "", "", -1, -1, -1, wSFCBOMTask.PartID, wSFCBOMTask.PartPointID, wSFCBOMTaskItem.MaterialID, "",
                        -1, wSFCBOMTaskItem.ReplaceType, wSFCBOMTaskItem.OutsourceType, null, -1, -1,
                        APSBOMSourceType.SFCBOMTask.getValue(), wErrorCode);
                wList.removeIf(p -> StringUtils.isNotEmpty(p.DeleteID));
                if (wList.size() <= 0) {
                    wResult.FaultCode += "提示：台车bom查询失败!";
                    return wResult;
                }

                if (wSFCBOMTaskItem.BOMItemID <= 0) {
                    wResult.FaultCode += "提示：线边库ID有误!";
                    return wResult;
                }

                WMSLineEdgeLibrary wWMSLineEdgeLibrary = WMSLineEdgeLibraryDAO.getInstance().SelectByID(wLoginUser,
                        wSFCBOMTaskItem.BOMItemID, wErrorCode);

                // ERP过账
                ZIF_MM_GET_WMS281_WSStub.ZFMM_GET_WMS281Response wms281Response = WMSLineEdgeLibraryDAO.getInstance()
                        .ERPUse(wLoginUser, wList.get(0), wSFCBOMTask,
                                wSFCBOMTaskItem,
                                wWMSLineEdgeLibrary,
                                wErrorCode);
                wGZList.add(wms281Response);
            }
            if (wGZList.stream().anyMatch(p -> String.valueOf(p.getIT_OUTPUT().getItem()[0].getZOK()).equals("N"))) {
                ZIF_MM_GET_WMS281_WSStub.ZFMM_GET_WMS281Response wms281Response = wGZList.stream()
                        .filter(p -> String.valueOf(p.getIT_OUTPUT().getItem()[0].getZOK()).equals("N")).findFirst()
                        .get();
                wSFCBOMTask.IsPost = 2;
                wSFCBOMTask.PostMsg = String.valueOf(wms281Response.getIT_OUTPUT().getItem()[0].getZMSG());
                SFCBOMTaskDAO.getInstance().UpdatePostInfo(wLoginUser, wSFCBOMTask, wErrorCode);
            } else if (wGZList.stream().allMatch(p -> String.valueOf(p.getIT_OUTPUT().getItem()[0].getZOK()).equals(
                    "Y"))) {
                wSFCBOMTask.IsPost = 1;
                wSFCBOMTask.PostMsg = "过账成功";
                SFCBOMTaskDAO.getInstance().UpdatePostInfo(wLoginUser, wSFCBOMTask, wErrorCode);
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<SFCScrapApprovalBPM> SFC_QueryDefaultScrapApprovalBPM(BMSEmployee wLoginUser, int wEventID) {
        ServiceResult<SFCScrapApprovalBPM> wResult = new ServiceResult<>();
        wResult.Result = new SFCScrapApprovalBPM();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            List<SFCScrapApprovalBPM> wList = SFCScrapApprovalBPMDAO.getInstance().SelectList(wLoginUser, -1, "",
                    wLoginUser.ID, "", -1,
                    -1, -1, -1, -1, new ArrayList<>(Collections.singletonList(0)), null, null, wErrorCode);
            if (wList != null && wList.size() > 0) {
                wResult.Result = wList.get(0);
                wResult.Result.VersionNo = "1.0";
            }
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<SFCScrapApprovalBPM> SFC_CreateScrapApprovalBPM(BMSEmployee wLoginUser,
                                                                         BPMEventModule wEventID) {
        ServiceResult<SFCScrapApprovalBPM> wResult = new ServiceResult<>();
        wResult.Result = new SFCScrapApprovalBPM();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            SFCScrapApprovalBPM wItem = new SFCScrapApprovalBPM();
            wItem.ID = 0;
            wItem.Code = SFCScrapApprovalBPMDAO.getInstance().GetNewCode(wLoginUser, wErrorCode);
            wItem.UpFlowID = wLoginUser.ID;
            wItem.UpFlowName = wLoginUser.Name;
            wItem.FlowType = BPMEventModule.ScrapApproval.getValue();
            wItem.Status = 0;
            wItem.Level = NCRLevel.Default.getValue();
            wItem.CreateTime = Calendar.getInstance();
            wItem.SubmitTime = Calendar.getInstance();
            wItem.Responsibility = 0;
            wItem.ReviewComments = 0;
            wItem.VersionNo = "1.0";
            wResult.Result = (SFCScrapApprovalBPM) SFCScrapApprovalBPMDAO.getInstance().BPM_UpdateTask(wLoginUser,
                    wItem, wErrorCode);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<SFCScrapApprovalBPM> SFC_SubmitScrapApprovalBPM(BMSEmployee wLoginUser,
                                                                         SFCScrapApprovalBPM wTask) {
        ServiceResult<SFCScrapApprovalBPM> wResult = new ServiceResult<>();
        wResult.Result = new SFCScrapApprovalBPM();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            if (wTask == null || wTask.ID <= 0) {
                return wResult;
            }

            // 保存子项物料
            if (wTask.Status == 1) {
                List<SFCScrapApprovalBPMItem> wSFCScrapApprovalBPMItemList = SFCScrapApprovalBPMItemDAO.getInstance()
                        .SelectList(wLoginUser, -1, wTask.ID, wErrorCode);
                if (wSFCScrapApprovalBPMItemList.size() > 0) {
                    SFCScrapApprovalBPMItemDAO.getInstance().DeleteList(wLoginUser, wSFCScrapApprovalBPMItemList,
                            wErrorCode);
                }
                for (SFCScrapApprovalBPMItem wSFCScrapApprovalBPMItem : wTask.SFCBOMTaskItemList) {
                    wSFCScrapApprovalBPMItem.ID = 0;
                    wSFCScrapApprovalBPMItem.SFCBOMTaskID = wTask.ID;
                    wSFCScrapApprovalBPMItem.ID = SFCScrapApprovalBPMItemDAO.getInstance().Update(wLoginUser,
                            wSFCScrapApprovalBPMItem, wErrorCode);
                }
            }

            if (wTask.Status == SFCBOMTaskStatus.NomalClose.getValue()) {
                wTask.StatusText = SFCBOMTaskStatus.NomalClose.getLable();
            } else if (wTask.Status == SFCBOMTaskStatus.ExceptionClose.getValue()) {
                wTask.StatusText = SFCBOMTaskStatus.ExceptionClose.getLable();
            }

            wResult.Result = (SFCScrapApprovalBPM) SFCScrapApprovalBPMDAO.getInstance().BPM_UpdateTask(wLoginUser,
                    wTask, wErrorCode);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());

            // ①推送物料到SAP(批量子表数据)
            if (wTask.Status == SFCBOMTaskStatus.NomalClose.getValue()) {
                List<SFCScrapApprovalBPMItem> wItemList = wTask.SFCBOMTaskItemList.stream()
                        .filter(p -> p.Status != 2).collect(Collectors.toList());
                SynchronizedToSap(wLoginUser, wTask, wErrorCode, wItemList);
            }
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<SFCScrapApprovalBPM> SFC_GetScrapApprovalBPM(BMSEmployee wLoginUser, int wID) {
        ServiceResult<SFCScrapApprovalBPM> wResult = new ServiceResult<>();
        wResult.Result = new SFCScrapApprovalBPM();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            wResult.Result = (SFCScrapApprovalBPM) SFCScrapApprovalBPMDAO.getInstance().BPM_GetTaskInfo(wLoginUser,
                    wID, "", wErrorCode);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<SFCScrapApprovalBPM>> SFC_QueryScrapApprovalBPMHistory(BMSEmployee wLoginUser, int wID,
                                                                                     String wCode, int wUpFlowID,
                                                                                     int wFollowerID, int wOrderID,
                                                                                     int wPartID, int wPartPointID,
                                                                                     int wBOMID,
                                                                                     int wLevel, Calendar wStartTime,
                                                                                     Calendar wEndTime) {
        ServiceResult<List<SFCScrapApprovalBPM>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            wResult.Result = SFCScrapApprovalBPMDAO.getInstance().SelectList(wLoginUser, wID, wCode, wUpFlowID, "",
                    wOrderID,
                    wPartID, wPartPointID, wBOMID, wLevel, null, wStartTime, wEndTime, wErrorCode);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<BPMTaskBase>> SFC_QueryScrapApprovalBPMEmployeeAll(BMSEmployee wLoginUser,
                                                                                 int wTagTypes, Calendar wStartTime,
                                                                                 Calendar wEndTime) {
        ServiceResult<List<BPMTaskBase>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            switch (TagTypes.getEnumType(wTagTypes)) {
                case Applicant:// 2发起
                    wResult.Result = SFCScrapApprovalBPMDAO.getInstance().BPM_GetSendTaskList(wLoginUser, wLoginUser.ID,
                            wStartTime,
                            wEndTime, wErrorCode);
                    break;
                case Dispatcher:// 1待做
                    wResult.Result = SFCScrapApprovalBPMDAO.getInstance().BPM_GetUndoTaskList(wLoginUser, wLoginUser.ID,
                            wErrorCode);
                    break;
                case Approver:// 4已做
                    wResult.Result = SFCScrapApprovalBPMDAO.getInstance().BPM_GetDoneTaskList(wLoginUser, wLoginUser.ID,
                            wStartTime,
                            wEndTime, wErrorCode);
                    break;
                default:
                    break;
            }

            if (wResult.Result.size() > 0) {
                wResult.Result = wResult.Result.stream().filter(p -> p.Status != 0).collect(Collectors.toList());
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<SFCScrapApprovalBPM>> SFC_QueryScrapApprovalBPMEmployeeAllNew(BMSEmployee wLoginUser,
                                                                                            Calendar wStartTime,
                                                                                            Calendar wEndTime,
                                                                                            int wOrderID,
                                                                                            int wPartID,
                                                                                            int wLevel,
                                                                                            int wStatus) {
        ServiceResult<List<SFCScrapApprovalBPM>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            List<SFCScrapApprovalBPM> wSendList;
            List<SFCScrapApprovalBPM> wToDoList = new ArrayList<>();
            List<SFCScrapApprovalBPM> wDoneList = new ArrayList<>();

            List<BPMTaskBase> wBaseList = SFCScrapApprovalBPMDAO.getInstance().BPM_GetSendTaskList(wLoginUser,
                    wLoginUser.ID,
                    wStartTime, wEndTime, wErrorCode);
            wSendList = CloneTool.CloneArray(wBaseList, SFCScrapApprovalBPM.class);
            // 查询数据
            List<SFCScrapApprovalBPM> wList = SFCScrapApprovalBPMDAO.getInstance().SFC_QueryListByMessage(wLoginUser,
                    wStartTime,
                    wEndTime, wErrorCode);
            if (wList.size() > 0) {
                wToDoList = wList.stream().filter(p -> p.StepID > 0).collect(Collectors.toList());
                wDoneList = wList.stream().filter(p -> p.StepID <= 0).collect(Collectors.toList());
            }

            List<Integer> wIDList = new ArrayList<>();

            for (SFCScrapApprovalBPM wMTCTask : wToDoList) {
                if (wIDList.contains(wMTCTask.ID))
                    continue;
                wMTCTask.TagTypes = TaskQueryType.ToHandle.getValue();
                wResult.Result.add(wMTCTask);
                wIDList.add(wMTCTask.ID);
            }

            for (SFCScrapApprovalBPM wMTCTask : wDoneList) {
                if (wIDList.contains(wMTCTask.ID))
                    continue;
                wMTCTask.TagTypes = TaskQueryType.Handled.getValue();
                wResult.Result.add(wMTCTask);
                wIDList.add(wMTCTask.ID);
            }

            for (SFCScrapApprovalBPM wMTCTask : wSendList) {
                if (wIDList.contains(wMTCTask.ID))
                    continue;
                wMTCTask.TagTypes = TaskQueryType.Sended.getValue();
                wResult.Result.add(wMTCTask);
                wIDList.add(wMTCTask.ID);
            }

            wResult.Result.removeIf(p -> p.Status == 0);

            // 订单
            if (wOrderID > 0) {
                wResult.Result = wResult.Result.stream().filter(p -> p.OrderID == wOrderID)
                        .collect(Collectors.toList());
            }
            // 工位
            if (wPartID > 0) {
                wResult.Result = wResult.Result.stream().filter(p -> p.PartID == wPartID).collect(Collectors.toList());
            }
            // 等级
            if (wLevel > 0) {
                wResult.Result = wResult.Result.stream().filter(p -> p.Level == wLevel).collect(Collectors.toList());
            }
            // 状态
            if (wStatus >= 0) {
                if (wStatus == 0) {
                    wResult.Result = wResult.Result.stream()
                            .filter(p -> p.Status != 20 && p.Status != 21 && p.Status != 22)
                            .collect(Collectors.toList());
                } else if (wStatus == 1) {
                    wResult.Result = wResult.Result.stream()
                            .filter(p -> p.Status == 20 || p.Status == 21 || p.Status == 22)
                            .collect(Collectors.toList());
                }
            }

            wResult.Result.sort((o1, o2) -> o2.CreateTime.compareTo(o1.CreateTime));
            wResult.Result.sort((o1, o2) -> {
                if (o1.TagTypes == 1) {
                    return -1;
                } else if (o2.TagTypes == 1) {
                    return 1;
                }
                return 0;
            });

            // 排序，已完工排在最后
            List<SFCScrapApprovalBPM> wFinishedList = wResult.Result.stream().filter(p -> p.Status == 20)
                    .collect(Collectors.toList());
            wResult.Result.removeIf(p -> p.Status == 20);
            wResult.Result.addAll(wFinishedList);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<SFCScrapApprovalBPM>> SFC_QueryScrapApprovalBPMList(BMSEmployee wLoginUser,
                                                                                  int wOrderID, int wPartID,
                                                                                  int wLevel, int wStatus,
                                                                                  Calendar wStartTime,
                                                                                  Calendar wEndTime,
                                                                                  String wMaterialNo,
                                                                                  String wMaterialName, int wIsLGL,
                                                                                  int wIsQualityLoss, int wCovaType) {
        ServiceResult<List<SFCScrapApprovalBPM>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            switch (wStatus) {
                case 1:
                    wResult.Result.addAll(SFCScrapApprovalBPMDAO.getInstance().SelectList(wLoginUser, wOrderID,
                            wPartID, -1, -1,
                            wLevel, StringUtils.parseListArgs(SFCBOMTaskStatus.NomalClose.getValue()), null, wStartTime,
                            wEndTime, wErrorCode));
                    break;
                case 0:
                    wResult.Result.addAll(
                            SFCScrapApprovalBPMDAO.getInstance().SelectList(wLoginUser, wOrderID, wPartID, -1, -1,
                                    wLevel, null,
                                    StringUtils.parseListArgs(SFCBOMTaskStatus.NomalClose.getValue(),
                                            SFCBOMTaskStatus.Canceled.getValue(), SFCBOMTaskStatus.Default.getValue(),
                                            25,
                                            SFCBOMTaskStatus.ExceptionClose.getValue()),
                                    wStartTime, wEndTime, wErrorCode));
                    break;
                default:
                    wResult.Result.addAll(SFCScrapApprovalBPMDAO.getInstance().SelectList(wLoginUser, wOrderID,
                            wPartID, -1, -1,
                            wLevel, null, null, wStartTime, wEndTime, wErrorCode));
                    break;
            }
            wResult.Result.sort((o1, o2) -> o2.SubmitTime.compareTo(o1.SubmitTime));

            if (wIsLGL >= 0) {
                wResult.Result = wResult.Result.stream().filter(p -> p.IsLGL == wIsLGL).collect(Collectors.toList());
            }

            if (wIsQualityLoss >= 0) {
                wResult.Result = wResult.Result.stream().filter(p -> p.IsQualityLoss == wIsQualityLoss)
                        .collect(Collectors.toList());
            }

            if (wCovaType > 0) {
                wResult.Result = wResult.Result.stream().filter(p -> p.CovaType == wCovaType)
                        .collect(Collectors.toList());
            }

            if (wResult.Result.size() <= 0 || wStatus == 1) {
                return wResult;
            }

            // ①通过物料号或物料名称模糊搜索偶换件评审单号
            if (StringUtils.isNotEmpty(wMaterialName) || StringUtils.isNotEmpty(wMaterialNo)) {
                List<Integer> wTaskIDList = SFCScrapApprovalBPMDAO.getInstance().SelectIDListByMaterial(wLoginUser,
                        wMaterialName, wMaterialNo, wErrorCode);
                wResult.Result = wResult.Result.stream().filter(p -> wTaskIDList.stream().anyMatch(q -> q == p.ID))
                        .collect(Collectors.toList());
            }

            List<BPMTaskBase> wBaseList = SFCScrapApprovalBPMDAO.getInstance().BPM_GetUndoTaskList(wLoginUser,
                    wLoginUser.ID,
                    wErrorCode);

            if (wBaseList == null || wBaseList.size() <= 0) {
                return wResult;
            }
            for (BPMTaskBase wTaskBase : wBaseList) {
                if (!(wTaskBase instanceof SFCScrapApprovalBPM))
                    continue;
                SFCScrapApprovalBPM wSFCScrapApprovalBPM = (SFCScrapApprovalBPM) wTaskBase;
                wSFCScrapApprovalBPM.TagTypes = TaskQueryType.ToHandle.getValue();
                for (int i = 0; i < wResult.Result.size(); i++) {
                    if (wResult.Result.get(i).ID == wSFCScrapApprovalBPM.ID)
                        wResult.Result.set(i, wSFCScrapApprovalBPM);
                }
            }
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<SFCScrapApprovalBPM> SFC_UpdateScrapApprovalBPM(BMSEmployee wLoginUser,
                                                                         SFCScrapApprovalBPM wData) {
        ServiceResult<SFCScrapApprovalBPM> wResult = new ServiceResult<>();
        wResult.Result = new SFCScrapApprovalBPM();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            wResult.Result = (SFCScrapApprovalBPM) SFCScrapApprovalBPMDAO.getInstance().BPM_UpdateTask(wLoginUser,
                    wData, wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> SFC_ReSendScrapApprovalBPM(BMSEmployee wLoginUser, int wTaskID) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            SFCScrapApprovalBPM wSFCScrapApprovalBPM = (SFCScrapApprovalBPM) SFCScrapApprovalBPMDAO.getInstance()
                    .BPM_GetTaskInfo(wLoginUser, wTaskID, "",
                            wErrorCode);
            if (wSFCScrapApprovalBPM == null || wSFCScrapApprovalBPM.ID <= 0
                    || wSFCScrapApprovalBPM.SFCBOMTaskItemList == null
                    || wSFCScrapApprovalBPM.SFCBOMTaskItemList.size() <= 0) {
                return wResult;
            }

            List<SFCScrapApprovalBPMItem> wItemList = wSFCScrapApprovalBPM.SFCBOMTaskItemList.stream()
                    .filter(p -> p.Status != 2).collect(Collectors.toList());
            SynchronizedToSap(wLoginUser, wSFCScrapApprovalBPM, wErrorCode, wItemList);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> IPT_TriggerScrapReviewProcess(BMSEmployee wLoginUser, int wIPTOutMaterialID) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            IPTOutsourcingMaterial wIPTOutsourcingMaterial = QMSServiceImpl.getInstance()
                    .IPT_OutsourcingMaterialInfo(wLoginUser,
                            wIPTOutMaterialID)
                    .Info(IPTOutsourcingMaterial.class);
            if (wIPTOutsourcingMaterial == null || wIPTOutsourcingMaterial.ID <= 0) {
                wResult.FaultCode = "创建任务失败，自修件登记数据不存在!";
                return wResult;
            }

            APIResult wAPiResult = CoreServiceImpl.getInstance().APS_StartInstance(wLoginUser, "8800");
            List<BPMActivitiTask> wBPMActivitiTask = wAPiResult.List(BPMActivitiTask.class);
            SFCScrapApprovalBPM wData = wAPiResult.Custom("data", SFCScrapApprovalBPM.class);

            wData.OrderID = wIPTOutsourcingMaterial.OrderID;
            wData.WBSNo = wIPTOutsourcingMaterial.WBSNo;
            wData.ProductID = wIPTOutsourcingMaterial.ProductID;
            wData.LineID = wIPTOutsourcingMaterial.LineID;
            wData.CustomerID = wIPTOutsourcingMaterial.CustomerID;
            wData.PartNo = wIPTOutsourcingMaterial.PartNo;
            wData.PartID = wIPTOutsourcingMaterial.PartID;
            wData.PartPointID = wIPTOutsourcingMaterial.StepID;
            wData.Disposal = StringUtils.Format("【{0}-{1}】自修件报废评审", wIPTOutsourcingMaterial.MaterialNo,
                    wIPTOutsourcingMaterial.MaterialName);
            wData.Status = 1;

            wData.SFCBOMTaskItemList = new ArrayList<>();
            SFCScrapApprovalBPMItem wSFCScrapApprovalBPMItem = new SFCScrapApprovalBPMItem();
            wSFCScrapApprovalBPMItem.ID = 0;
            wSFCScrapApprovalBPMItem.SFCBOMTaskID = 0;
            wSFCScrapApprovalBPMItem.BOMItemID = 0;
            wSFCScrapApprovalBPMItem.BOMID = 0;
            wSFCScrapApprovalBPMItem.MaterialID = wIPTOutsourcingMaterial.MaterialID;
            wSFCScrapApprovalBPMItem.MaterialNo = wIPTOutsourcingMaterial.MaterialNo;
            wSFCScrapApprovalBPMItem.MaterialName = wIPTOutsourcingMaterial.MaterialName;
            wSFCScrapApprovalBPMItem.OutsourceType = wIPTOutsourcingMaterial.OutSourceType;
            wSFCScrapApprovalBPMItem.ReplaceType = 0;
            wSFCScrapApprovalBPMItem.MaterialNumber = wIPTOutsourcingMaterial.FQTY;
            wSFCScrapApprovalBPMItem.SapType = 1;
            wData.SFCBOMTaskItemList.add(wSFCScrapApprovalBPMItem);

            // ①辅助属性赋值
            wData.Disposal_txt_ = wData.Disposal;
            wData.LineName_txt_ = wIPTOutsourcingMaterial.LineName;
            wData.ProductNo_txt_ = wIPTOutsourcingMaterial.ProductNo;
            wData.PartNo_txt_ = wIPTOutsourcingMaterial.PartNo;
            wData.CustomerName_txt_ = wIPTOutsourcingMaterial.CustomerName;
            wData.PartName_txt_ = wIPTOutsourcingMaterial.PartName;
            wData.PartPointName_txt_ = wIPTOutsourcingMaterial.StepName;

            CoreServiceImpl.getInstance().APS_CompleteInstance(wLoginUser, wData, wBPMActivitiTask.get(0).ID);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<String> WMS_ExportQualityLoss(BMSEmployee wLoginUser, Calendar wStartTime, Calendar wEndTime) {
        ServiceResult<String> wResult = new ServiceResult<>();
        wResult.Result = "";
        try {
            OutResult<Integer> wErrorCode = new OutResult<Integer>(0);

            MyExcelSheet wMyExcelSheet = SFCQualityLossBPMDAO.getInstance().GetMyExcelSheet(wLoginUser, wStartTime,
                    wEndTime, wErrorCode);

            List<MyExcelSheet> wMyExcelSheetList = new ArrayList<MyExcelSheet>(
                    Collections.singletonList(wMyExcelSheet));

            wResult.Result = ExcelUtil.ExportData(wMyExcelSheetList, "质量损失清单");

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> SFC_ImportSFCOutMaterialConfig(BMSEmployee wLoginUser, ExcelData wExcelData) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            if (wExcelData == null || wExcelData.sheetData == null || wExcelData.sheetData.size() <= 0) {
                wResult.FaultCode += "提示：Excel格式错误!";
                return wResult;
            }

            ExcelSheetData wExcelSheetData = wExcelData.sheetData.get(0);
            int wIndex = 0;
            for (ExcelLineData wExcelLineData : wExcelSheetData.lineData) {
                if (wIndex == 0) {
                    wIndex++;
                    continue;
                }

                if (wExcelLineData.colData.size() <= 0 || StringUtils.isEmpty(wExcelLineData.colData.get(0))) {
                    wIndex++;
                    continue;
                }

                String wPartCompName = wExcelLineData.colData.size() > 0 ? wExcelLineData.colData.get(0) : "";
                if (StringUtils.isEmpty(wPartCompName)) {
                    wIndex++;
                    continue;
                }
                String wProductNo = wExcelLineData.colData.size() > 1 ? wExcelLineData.colData.get(1) : "";
                if (StringUtils.isEmpty(wProductNo)) {
                    wIndex++;
                    continue;
                }
                String wLineName = wExcelLineData.colData.size() > 2 ? wExcelLineData.colData.get(2) : "";
                if (StringUtils.isEmpty(wLineName)) {
                    wIndex++;
                    continue;
                }
                String wPartName = wExcelLineData.colData.size() > 3 ? wExcelLineData.colData.get(3) : "";
                if (StringUtils.isEmpty(wPartName)) {
                    wIndex++;
                    continue;
                }
                String wMaterialNo = wExcelLineData.colData.size() > 5 ? wExcelLineData.colData.get(5) : "";
                if (StringUtils.isEmpty(wPartName)) {
                    wIndex++;
                    continue;
                }
                String wSuppliers = wExcelLineData.colData.size() > 6 ? wExcelLineData.colData.get(6) : "";

                double wCheckPeriod = wExcelLineData.colData.size() > 7
                        ? StringUtils.parseDouble(wExcelLineData.colData.get(7))
                        : 0;
                String wIsPartCode = wExcelLineData.colData.size() > 8 ? wExcelLineData.colData.get(8) : "否";
                int wIsPartCodeID = wIsPartCode.equals("是") ? 1 : 2;

                int wProductID = APSConstans.GetFPCProducID(wProductNo);
                if (wProductID <= 0) {
                    wResult.FaultCode += "提示：Excel数据格式错误!错误行：" + (wIndex + 1);
                    return wResult;
                }
                int wLineID = APSConstans.GetFMCLineID(wLineName);
                if (wLineID <= 0) {
                    wResult.FaultCode += "提示：Excel数据格式错误!错误行：" + (wIndex + 1);
                    return wResult;
                }
                int wPartID = APSConstans.GetFPCPartID(wPartName);
                if (wPartID <= 0) {
                    wResult.FaultCode += "提示：Excel数据格式错误!错误行：" + (wIndex + 1);
                    return wResult;
                }
                List<MSSMaterial> wMSSMaterialList = WMSServiceImpl.getInstance()
                        .MSS_QueryMaterialList(wLoginUser, wMaterialNo).List(MSSMaterial.class);
                if (wMSSMaterialList == null || wMSSMaterialList.size() <= 0) {
                    wResult.FaultCode += "提示：Excel数据格式错误!错误行：" + (wIndex + 1);
                    return wResult;
                }
                List<Integer> wMaterialIDList = wMSSMaterialList.stream().map(p -> p.ID).distinct()
                        .collect(Collectors.toList());

                List<SFCOutMaterialConfig> wSFCOutMaterialConfigList = SFCOutMaterialConfigDAO.getInstance().SelectList(
                        wLoginUser, -1, wProductID, wLineID, -1,
                        -1, -1, wPartID, wMaterialIDList, wErrorCode);
                if (wSFCOutMaterialConfigList != null && wSFCOutMaterialConfigList.size() > 0) {
                    wIndex++;
                    continue;
                }

                SFCOutMaterialConfig wSFCOutMaterialConfig = new SFCOutMaterialConfig(0, wProductID, wLineID,
                        wMSSMaterialList.get(0).ID, wCheckPeriod, wIsPartCodeID, 1, wPartCompName, wPartID);
                int wNewID = SFCOutMaterialConfigDAO.getInstance().Update(wLoginUser, wSFCOutMaterialConfig,
                        wErrorCode);
                if (wNewID > 0) {
                    List<String> wSupperList = new ArrayList<>();
                    if (wSuppliers.contains(",")) {
                        wSupperList = StringUtils.parseList(wSuppliers.split(","));
                    } else if (wSuppliers.contains("，")) {
                        wSupperList = StringUtils.parseList(wSuppliers.split("，"));
                    } else {
                        wSupperList = new ArrayList<>(Collections.singletonList(wSuppliers));
                    }
                    for (String wName : wSupperList) {
                        SFCOutMaterialConfigItem wSFCOutMaterialConfigItem = new SFCOutMaterialConfigItem();
                        wSFCOutMaterialConfigItem.ID = 0;
                        wSFCOutMaterialConfigItem.ConfigID = wNewID;
                        wSFCOutMaterialConfigItem.SupplierName = wName;
                        wSFCOutMaterialConfigItem.DeviceModel = "";
                        SFCOutMaterialConfigItemDAO.getInstance().Update(wLoginUser, wSFCOutMaterialConfigItem,
                                wErrorCode);
                    }
                }

                wIndex++;
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<FPCRoutePartPoint>> APS_QueryPartPointListByOrderAndRouteAndPart(BMSEmployee wLoginUser,
                                                                                               int wOrderID, int wRouteID, int wPartID) {
        ServiceResult<List<FPCRoutePartPoint>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            // ①查询BOP工序
            List<FPCRoutePartPoint> wFPCRoutePartPointList = FMCServiceImpl.getInstance()
                    .FPC_QueryRoutePartPointListByRouteID(wLoginUser, wRouteID, wPartID).List(FPCRoutePartPoint.class);
            // ②查询台车BOM工序
            List<FPCRoutePartPoint> wBOMPartPointList = APSBOMItemDAO.getInstance()
                    .APS_QueryBOMPartPointList(wLoginUser, wOrderID, wPartID, wErrorCode);
            // ③添加数据
            if (wBOMPartPointList != null && wBOMPartPointList.size() > 0) {
                for (FPCRoutePartPoint fpcRoutePartPoint : wBOMPartPointList) {
                    if (wFPCRoutePartPointList.stream()
                            .noneMatch(p -> p.PartPointID == fpcRoutePartPoint.PartPointID)) {
                        wFPCRoutePartPointList.add(fpcRoutePartPoint);
                    }
                }
            }
            // ④排序
            wFPCRoutePartPointList.sort(Comparator.comparing(FPCRoutePartPoint::getPartPointID));
            // ⑤返回结果
            wResult.Result = wFPCRoutePartPointList;

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error("APS_QueryPartPointListByOrderAndRouteAndPart", e);
        }
        return wResult;
    }
}
